Reputation: 1406
I have a React class based component. I want to pass a child component a function from this parent component. When the child component does an onClick event I will call the parent's function. Then, I want to update state in the parent component based on what element was clicked in the child component.
QuestionsSection is the parent component with state:
class QuestionsSection extends React.Component {
constructor(props) {
super(props);
this.state = {
isVisible: "option1"
};
}
handleOptionChange = e => {
this.setState({
isVisible: e.target.value
});
alert("function called");
}
render() {
return (
<div>
<QuestionsItems
isVisible={this.state.isVisible}
handleOptionChange={() => this.handleOptionChange()}
</div>
);
}
}
QuestionsItems is the child component that is stateless/function component:
const QuestionsItems = (props) => {
return (
<div>
<Container className="d-flex flex-md-row flex-column justify-content-center">
<Row className="d-flex flex-md-column flex-row order-1 justify-content-center">
<Col className={props.isVisible === 'option1' ? 'highlighted' : 'questions-section'}>
<label className="cursor-pointer" onClick={props.handleOptionChange}>
<input
type="radio"
value="option1"
checked={props.isVisible === 'option1'}
onChange={props.handleOptionChange}>
</input>
<Col xs={{span: 12}}>
<img src={questions1} alt="pic" height="50"/>
</Col>
<p>Ask a question</p>
</label>
</Col>
<Col className={props.isVisible === 'option2' ? 'highlighted' : 'questions-section'}>
<label className="cursor-pointer" onClick={props.handleClick}>
<input
type="radio"
value="option2"
checked={props.isVisible === 'option2'}
onChange={props.handleOptionChange}>
</input>
<Col xs={{span: 12}}>
<img src={questions2} alt="pic" height="50"/>
</Col>
<p>Vote on everything</p>
</label>
</Col>
</Row>
<Row className="d-flex flex-md-column flex-row image-container order-md-2 order-3 justify-content-center">
<Col
xs={{span: 12}}
className="featured-question order-lg-2 order-3">
{
props.isVisible === 'option1' ?
<Col xs={{span: 12}}>
<img src={questionsBig1} alt="featured image"/>
</Col>
: ""
}
{
props.isVisible === 'option2' ?
<Col xs={{span: 12}}>
<img src={questionsBig2} alt="featured image" />
</Col>
: ""
}
</Col>
</Row>
</Container>
</div>
);
}
This component has a lot of markup/Bootstrap syntax. Ignore that, it's just two elements that both have an onClick event. The third part is just ternary logic that displays either the first or second element based on value.
The problem I am having lies with updating this.state in the parent component. e.target.value is undefined. How can I update the QuestionsSection's (the parent component) state based on which element the child component clicks? Is it a matter of passing the value on the clicked element in the child component back to the parent component?
Upvotes: 1
Views: 6538
Reputation: 38757
In the parent, you aren’t passing any arguments to the handler where setState() is being called currently. You need to pass the value passed from the child to the handler, in this the change event. Before making the following change, try logging out e
in handleOptionChange
, you will see it's undefined. Try the following:
handleOptionChange={(e)=> this.handleOptionChange(e)}
You can also shorten this:
handleOptionChange={this.handleOptionChange}
Hopefully that helps!
Upvotes: 1
Reputation: 2403
You need to pass handleOptionChange
as a callback of handleOptionChange
prop
Change this:
handleOptionChange={() => this.handleOptionChange()}
to
handleOptionChange={this.handleOptionChange}
This happens because the handler expects an event that is not passed to the function.
Upvotes: 1