【问题标题】:Can a Child component Access its Containing Component's Methods?子组件可以访问其包含组件的方法吗?
【发布时间】:2019-01-26 23:00:13
【问题描述】:

我见过与此类似的问题,但他们通常是在谈论父组件访问子组件的方法或通过 props 传入方法。我的问题是针对特定情况,使用props.children,并且让任何子组件都能够调用正在呈现props.children 的父组件上的方法。

我试图实现的简化示例:

class WrapperComponent extends React.Component {

constructor(props){
    super(props);
    this.handleInputChange = this.handleInputChange.bind(this)
}

handleInputChange(e){
    console.log("neat, you changed the input")
}

render() {
    return (
        <form>
            {this.props.children}
        </form>
    )
  }
}

以及调用所述组件并将子组件作为道具传递的组件。

const Component = (props) => {
return(
    <WrapperComponent>
        <div className="form-group" >
            <label>
                <div>Text</div>
                <input onChange={this.handleInputChange} type={"text"}/>
            </label>
        </div>
    </WrapperComponent>
)
}

我的想法是我可以渲染一个包含某些逻辑的组件,并将元素作为子元素传递给该组件以供渲染,而且props.children 然后可以在包装器中调用所述逻辑,所以我可以通过在不同用例中的不同子级中,但处理方式始终相同。有没有办法做到这一点?

【问题讨论】:

  • 只要通过 props 传递给子组件即可。

标签: javascript reactjs methods


【解决方案1】:

您可以使用一些内置的 React 好东西克隆您的元素并向它们添加新的道具:

class WrapperComponent extends React.Component {

constructor(props){
    super(props);
    this.handleInputChange = this.handleInputChange.bind(this)
}

handleInputChange(e){
    console.log("neat, you changed the input")
}

render() {
    return (
        <form>
            {React.Children.map(
                this.props.children, 
                el => React.cloneElement(el, {onInputChange: this.handleInputChange})
            )}
        </form>
    )
  }
}

然后(移除 WrapperComponent):

const Component = (props) => {
  return(
        <div className="form-group" >
            <label>
                <div>Text</div>
                <input onChange={props.onInputChange} type={"text"}/>
            </label>
        </div>
  )
}

然后:

ReactDOM.render(
    <WrapperComponent><Component /></WrapperComponent>,
    document.getElementById('root')
)

【讨论】:

  • 嘿,这工作得很好,我将答案标记为正确,但我确实在控制台中收到错误消息“未知事件处理程序属性onInputChange。它将被忽略”。如果在 cloneElement() 函数中我写 {onChange:this.handleInputChange} 那么它可以工作,但是它将该事件处理程序应用于每个子组件,理想情况下我会使用道具从孩子控制它,而不仅仅是盲目地将它应用于所有元素,因为有些孩子可能有不同的处理程序(用于验证或提交)
  • 好的,我开始工作了,遵循最后一步非常重要,将子组件呈现为组件本身 () 或仅制作确保所有子项(如果只是 jsx)都在一个容器中传递,我通过用 包装子项内容来修复它
【解决方案2】:

是的,有一种方法,但它并不简单,您可能需要考虑另一种方法。

为了让子组件能够访问任意父组件的方法,父组件必须覆盖子组件的 props。这可以使用父级的render() 函数中的React.cloneElement 来完成。在您的示例中:

class WrapperComponent extends React.Component {

constructor(props){
    super(props);
    this.handleInputChange = this.handleInputChange.bind(this)
}

handleInputChange(e){
    console.log("neat, you changed the input")
}

render() {
    return (
        <form>
            {React.Children.map(this.props.children, child => (
                React.cloneElement(child, {handleInputChange: this.handleInputChange}
            )}
        </form>
    )
  }
}

然后,您可以通过this.props.handleInputChange 访问child 中的方法。

【讨论】:

  • 非常感谢!你说你会建议一种不同的方法,除了增加复杂性之外,还有什么特殊原因导致这可能是一种糟糕的方法吗?
  • 我主要是从可读性/可维护性的角度说的。当组件的行为由任意容器定义时,很难理解发生了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-03
  • 2021-04-21
  • 1970-01-01
  • 2019-06-07
  • 2017-12-24
  • 1970-01-01
相关资源
最近更新 更多