简体   繁体   中英

React: Pass function to child component as props, call onClick in child component

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?

Here's the error: 在此处输入图片说明

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!

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM