【问题标题】:How to call parent function from custom child component?如何从自定义子组件调用父函数?
【发布时间】:2019-02-14 10:11:45
【问题描述】:

我有两个组件,父组件和子组件。

家长:

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 函数,因为它只是调用父函数并恢复布尔值。所以在使用中再传一遍是没有意义的。

问题是我怎样才能通过这个isSelectisSelect={this.isSelect} 似乎被 &lt;Header isSelect={this.isSelect} /&gt; 覆盖。

【问题讨论】:

  • 你的问题我不清楚,你想从呈现 Parent 的组件中传递 isSelect,现在在 parent 本身内部,对吗?另外,我认为您提供的代码中存在一个错误......因为您正在渲染 Child 组件 2 次,首先在渲染父级时,您正在渲染 Child 元素并将渲染的组件传递给 Parent,然后在父级内部您正在以名称 Header 呈现渲染的组件

标签: reactjs


【解决方案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'>

【讨论】:

    【解决方案2】:

    JS 类方法默认没有绑定,所以如果你像在代码中那样传递isSelectthis 将是未定义的(this.setState 将不起作用)。

    您可以将调用 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>

    【讨论】:

      猜你喜欢
      • 2020-03-25
      • 1970-01-01
      • 2021-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-07
      • 1970-01-01
      相关资源
      最近更新 更多