I have two child components. The first child is an image and the second child is a search input. When I type something in the input field, I want the image to hide itself. The passing of data from the second child to the parent goes well. But the first child still appears...
Parent:
class Main extends React.Component {
constructor() {
super();
this.state = {
displayValue: 'block'
};
}
hideImage = () => () => {
alert('You pressed a key, now the apple should be gone')
this.setState ({
displayValue: 'none'
});
};
render() {
return (
<div>
<Image />
<Search hideImage={this.hideImage()}/>
</div>
);
}
}
ReactDOM.render(<Main />, document.getElementById('root'));
First Child:
export default class Image extends Component {
render() {
return (
<div>
<img style={{display : this.props.displayValue}} src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTAxoq2YSBjoS0Lo3-zfqghoyNzZ9jHxoOc5xuFBoopMtKP6n4B"></img>
</div>
)
}
}
Second Child:
export default class Search extends Component {
render() {
return (
<div>
<input onInput={this.props.hideImage} placeholder="Search someting"></input>
</div>
)
}
}
You have to pass the displayValue state into your Image component as a prop. Also you have to pass the hideImage function without initializing it using the two brackets. The below code should work for you.
class Main extends React.Component {
constructor() {
super();
this.state = {
displayValue: 'block'
};
}
hideImage = () => () => {
alert('You pressed a key, now the apple should be gone')
this.setState ({
displayValue: 'none'
});
};
render() {
return (
<div>
<Image displayValue={this.state.displayValue}/>
<Search hideImage={this.hideImage}/>
</div>
);
}
}
You just had a couple of typos.
class Image extends React.Component {
render() {
return (
<div>
<img
style={{ display: this.props.displayValue }}
src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTAxoq2YSBjoS0Lo3-zfqghoyNzZ9jHxoOc5xuFBoopMtKP6n4B"
alt="altprop"
/>
</div>
);
}
}
// Second Child:
class Search extends React.Component {
render() {
return (
<div>
<input onInput={this.props.hideImage} placeholder="Search someting" />
</div>
);
}
}
class Main extends React.Component {
constructor() {
super();
this.state = {
displayValue: "block"
};
}
hideImage(e) {
e.preventDefault();
alert("You pressed a key, now the apple should be gone");
this.setState({
displayValue: "none"
});
};
render() {
return (
<div>
<Image displayValue={this.state.displayValue}/>
<Search hideImage={this.hideImage.bind(this)} />
</div>
);
}
}
Call your Image component like this
<Image displayValue={this.state.displayValue} />
It should then already work, but here is a shorter way to write your code.
// First Child:
const Image = ({displayValue}) => <div>
<img alt='' style={{display : displayValue}} src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTAxoq2YSBjoS0Lo3-zfqghoyNzZ9jHxoOc5xuFBoopMtKP6n4B"></img>
</div>
Related
I am trying to change colour of text in h1 tag when I click button. I am calling change colour function but when onclick it executes at that time it is showing error in the inside statement [ this.styling_text.color="black" ]
import React,{Component} from 'react';
class InlineDynamic extends Component{
changeColor = () =>{
this.styling_text.color="black"
};
render(){
const styling_text = {color:"red"};
return(
<div>
<h1 style={styling_text} >Change My Colour !! on click</h1>
<button onClick={this.changeColor}>click me</button>
</div>
);
}
}
export default InlineDynamic;
If you want to update the color property, add styling_text object to the component state:
class InlineDynamic extends React.Component {
constructor() {
super();
this.state = {
styling_text: { color: "red" },
};
}
changeColor = () => {
this.setState({ styling_text: { color: "black" } });
};
render() {
const {styling_text} = this.state;
return (
<div>
<h1 style={styling_text}>Change My Colour !! on click</h1>
<button onClick={this.changeColor}>click me</button>
</div>
);
}
}
EDIT:
Other solution is to use React.createRef :
class InlineDynamic extends React.Component {
constructor() {
super();
this.styling_text = React.createRef(null);
}
componentDidMount() {
this.styling_text.current.style.color = "black";
}
changeColor = () => {
this.styling_text.current.style.color = "red";
};
render() {
return (
<div>
<h1 ref={this.styling_text}>Change My Colour !! on click</h1>
<button onClick={this.changeColor}>click me</button>
</div>
);
}
}
Declare styling_text outside of render
class InlineDynamic extends Component{
changeColor = () =>{
this.styling_text.color="black"
};
styling_text = {color:"red"};
render(){
return(
<div>
<h1 style={styling_text} >Change My Colour !! on click</h1>
<button onClick={this.changeColor}>click me</button>
</div>
);
}
}
I am new to React and I am finding it difficult to pass props from one component to another.
This is the first component
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
// show:true
};
}
counter = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div className="">
<div>{this.state.count}</div>
</div>
);
}
}
and this is the second
export default class Button extends React.Component {
render() {
return (
<div className="">
<App />
<button onClick={this.counter}>Click me</button>
</div>
);
}
}
How do I make the counter count by passing props in the apps component
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
// show:true
};
}
counter = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div className="">
<div>{this.state.count}</div>
<Button counter={this.counter} />
</div>
);
}
}
export default class Button extends React.Component {
render() {
return (
<div className="">
<button onClick={this.props.counter}>Click me</button>
</div>
);
}
}
I have two React Components, Gallery & Image. The Image Component uses a Gallery function as props.
Can I do the call in the render without an arrow function?
Image component:
class Image extends React.Component {
constructor(props) {
super(props);
this.state = {
filter: 'none',
};
}
render() {
return (
<div>
<button className="image-icon" onClick={() => this.props.handleClone(this.props.i)} />
</div>
);
}
}
Gallery component:
class Gallery extends React.Component {
constructor(props) {
super(props);
this.handleClone = this.handleClone.bind(this);
this.state = {
images: [],
};
}
handleClone(i) {
var newImages = this.state.images;
newImages = newImages.slice(0, i + 1).concat(newImages.slice(i));
this.setState({
images: newImages,
});
}
render() {
return (
<div>
<div className="gallery-root">
{this.state.images.map((dto, i) => {
return <Image key={'image-' + dto.id + '-' + i} i={i} handleClone={this.handleClone} />;
})}
</div>
</div>
);
}
}
Thanks.
class Image extends React.Component {
constructor(props) {
super(props);
this.state = {
filter: 'none'
};
}
handleClick = () => {
this.props.handleClone(this.props.i);
};
render() {
return (
<div>
<button className="image-icon" onClick={this.handleClick} />
</div>
);
}
}
So I have a component "itemSelection" and inside of it I map through an api response like this
<div className="row">
{this.state.items.map(i => <Item name={i.name} quantity={i.quantity} />)}
</div>
Here the state of "Item" component
constructor(props){
super(props);
this.state = {
visible: false,
selected: false,
}
}
How could I pass the state of "Item" component to "itemSelection" component?
Sending data back up to your parent component should be done by using props.
Fairly common question, see this post for the long answer.
As according to me, If I understood your question you want to call the state of the child component to the parent component.
//Child.js
import s from './Child.css';
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
export default withStyles(s)(Child);
//Parent.js
class Parent extends Component {
render() {
onClick() {
this.refs.child.getAlert()
}
return (
<div>
<Child ref="child" />
<button onClick={this.onClick.bind(this)}>Click</button>
</div>
);
}
}
Also, you can get the code reference from the link: https://github.com/kriasoft/react-starter-kit/issues/909
This a little tricky but Maybe, its help you solving your problem.
//Parent.js
class Parent extends Component {
component(props) {
super(props)
this.state = {
test: 'abc'
}
}
ParentFunction = (value) => {
this.state.test = value;
this.setState(this.state);
}
render() {
return (
<div>
<Child
test={this.state.test}
ParentFunction={this.ParentFunction}
/>
</div>
);
}
}
//Child.js
import s from './Child.css';
class Child extends Component {
component(props) {
super(props)
this.state = {
test: props.test
}
}
handleChange = () => {
this.state.test = event.target.value;
this.setState(this.state);
this.handleOnSave()
}
handleOnSave = () => {
this.props.ParentFunction(this.state.test);
}
render() {
return (
<div>
<input type="text" onChange={this.handleChange} />
</div>
);
}
}
export default withStyles(s)(Child);
i'm using ReactJS without FLux or Redux. I want the grand child component can communicate (read/update data) with his grandparents component.
Here's the parent component App:
export default class App extends React.Component {
static propTypes = {
children: React.PropTypes.object.isRequired
};
constructor(props) {
super(props);
this.state = {
tabActive: 0,
};
}
setTabActive(item) {
this.setState({
tabActive: item,
});
}
render() {
return (
<div>
<Header tabActive={this.state.tabActive} />
<Content>
{this.props.children}
</ Content>
<Footer />
</div>
);
}
}
child component Header:
export default class Header extends React.Component {
render() {
return (
<div>
....
<SettingTabBar tabActive={this.props.tabActive} />
</div>
);
}
}
Child of child component SettingTabBar:
export default class SettingTabBar extends React.Component {
constructor(props) {
super(props);
this.state = { activeTab: this.props.tabActive };
}
render() {
if (location.pathname.indexOf('setting') > 0) {
return (
<Tabs activeTab={this.state.activeTab} onChange={tabId => this.setState({ activeTab: tabId })} ripple>
<Tab>SETTING</Tab>
<Tab>CHARTS</Tab>
<Tab>HELP</Tab>
</Tabs>
);
}
return null;
}
}
Are there anyway to make SettingTabBar component can update data to App/Header component via function setTabActive() when onChange?
For communication with grandparent and grandchild, you can use context. It's not recomended, but it's working.
// root component
class App extends React.Component {
constructor(props){
super(props);
this.state = {
activeMenu: "none"
};
}
getChildContext() {
return {
rootCallback: menuName => {
this.setState({activeMenu: menuName});
}
}
}
render() {
return (
<div>
<div>Current active menu is: <strong>{this.state.activeMenu}</strong></div>
<Child />
</div>
);
}
}
// declare childContextTypes at context provider
App.childContextTypes = {
rootCallback: React.PropTypes.function
}
// intermediate child
class Child extends React.Component {
render() {
return (
<div>
<GrandChild />
</div>
);
}
}
// grand child
class GrandChild extends React.Component {
render() {
return (
<div>
{/* get context by using this.context */}
<button
type="button"
onClick={()=>this.context.rootCallback("one")}
>
Activate menu one
</button>
<button
type="button"
onClick={()=>this.context.rootCallback("two")}
>
Activate menu two
</button>
<button
type="button"
onClick={()=>this.context.rootCallback("three")}
>
Activate menu three
</button>
</div>
)
}
}
// also declare contextTypes at context consumer
GrandChild.contextTypes = {
rootCallback: React.PropTypes.function
}
// render it to DOM
ReactDOM.render(<App /> , document.getElementById('app-mount'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app-mount"></div>