如何从自定义子组件调用父函数?

时间:2019-02-14 10:11:46

标签: reactjs

我有两个部分,父母和孩子。

父母:

class Parent extends React.Component {
  constructor(){
    super()
    this.state = {
      select: false
    }
  }
  isSelect(){
    this.setState({...this.state, select: !this.state.select})
  }
  render(){
    const { Header, children } = this.props
    return (
      <>
        <Header isSelect={this.isSelect} />
      </>
    )
  }
}

孩子:

class Child extends React.Component {
  render(){
    const {title, isSelect} = this.props
    /*problem here! can not get isSelect*/
    return(
      <div>
        <p>{title}</p>
        <button onClick={this.isSlect}>choose</button>
        /*problem here! isSelect*/
      </div>
    )
  }
}

使用中:

<Parent Header={<Child title='just for test' />} />

可以渲染组件,但不能渲染单击事件。 我想为子组件自动设置isSlect函数,因为它只是调用父函数并恢复布尔值。因此再次使用它没有意义。

问题是如何通过此isSelect?似乎isSelect={this.isSelect}已被<Header isSelect={this.isSelect} />覆盖。

2 个答案:

答案 0 :(得分:1)

您可以将Header的行为更改为通过参数传递isSelect回调的函数:

render() {
    const { Header, children } = this.props

    return Header(this.isSelect)
}

组件现在可以根据需要分配接收的功能:

<Parent Header={clicked => <Child title='just for test' isSelect={clicked} />} />

工作示例:

class Parent extends React.Component {
    constructor(props) {
        super(props) //Don't forget to send the props in super
        this.state = {
            select: false
        }
    }

    isSelect = () => { //Arrow function to avoid having to bind it
        this.setState({ ...this.state, select: !this.state.select })
        console.log('Selected')
    }

    render() {
        const { Header, children } = this.props

        return Header(this.isSelect)
    }
}

class Child extends React.Component {
    render() {
        const { title, isSelect } = this.props

        return (
            <div>
                <p>{title}</p>
                <button onClick={isSelect}>choose</button> {/* Careful, you do not need to add 'this.' */}
            </div>
        )
    }
}

ReactDOM.render(<Parent Header={clicked => <Child title='just for test' isSelect={clicked} />} />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
<div id='root'>

答案 1 :(得分:0)

JS类方法默认情况下不受约束,因此,如果像在代码中那样传递isSelect,则this将是未定义的(而this.setState将不起作用)。 / p>

您可以将调用isSelect的匿名欠款函数传递给子项:

<Child isSelect={() => this.isSelect()} />

或将其绑定在Parent建设者中:

this.isSelect = this.isSelect.bind(this)

或使用public class fields(如果您使用Babel或其他一些编译器,它们仍处于试验阶段):

class Parent extends React.Component {
    …

    isSelect = () => {
        this.setState(…)
    }
}

React docs: handling events

工作示例:

class Parent extends React.Component {
  constructor(){
    super()
    this.state = {
      select: false
    }
    this.isSelect = this.isSelect.bind(this)
  }
  isSelect(){
    this.setState({...this.state, select: !this.state.select})
  }
  render(){
    const { Header, children } = this.props
    return (
      <div>
        <Child isSelect={this.isSelect} />
        <Child isSelect={() => this.isSelect()} /> {/* this one will work even without .bind in the constructor */}
        <code>{JSON.stringify(this.state, null, 2)}</code>
      </div>
    )
  }
}

class Child extends React.Component {
  render(){
    return(
      <div>
        <button onClick={this.props.isSelect}>choose</button>
      </div>
    )
  }
}



ReactDOM.render(
  (<Parent/>),
  document.querySelector("#root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>