【问题标题】:React - Remove prop from childReact - 从孩子身上移除道具
【发布时间】:2017-08-19 20:12:54
【问题描述】:

我需要从一个孩子身上移除一个道具。

我有一个容器元素,它使用子元素的属性来对子元素执行一些增强。该属性应该在渲染之前从子元素中移除。

<AsyncContainer>
   <Button onClick={this.asyncStuff} asyncHandler="onClick"/>
</AsyncContainer>

asyncHandler 属性应该在渲染之前从按钮中移除。

AsyncContainer 使用React.cloneElement(child, properties)

我已尝试将 asyncHandler 属性设为空,将其设置为未定义并从 child.props 中删除该属性。看来再也无法摆脱这个属性了。

【问题讨论】:

  • props 在 React 中是不可变的,因此不能由组件本身更改。父级必须修改prop,然后将其传递给组件。
  • 你不能对孩子的道具做任何事情,因为它们是只读的:facebook.github.io/react/docs/…
  • 也许你可以克隆孩子并以某种方式替换属性对象?

标签: javascript reactjs


【解决方案1】:

根据 cmets,您不能直接修改道具,因为它们是不可变的。

但是,我认为我有一个简单的解决方案来解决这个问题。我不知道它是什么库或它是如何工作的,所以这可能有效也可能无效。但是,这是关于如何在组件安装之前移除道具的一般答案。

话虽如此,我会尝试创建自己的组件来呈现&lt;Button /&gt;

class MyButtonComponent extends React.Component {

...

  render() {
    return <Button onClick={this.props.onClickHandler} />;
  }
}

然后在你想要做增强的组件中:

render() {
  <AsyncContainer>
    <MyButtonComponent onClickHandler={this.asyncStuff} asyncHandler="onClick"/>
  </AsyncContainer>
}

这样你在&lt;Button /&gt; 组件上维护你的onClick 事件监听器,但你不会传递非法的asyncHandler 属性。


编辑:

或者,您也可以这样做:

class MyButtonComponent extends React.Component {

...

  componentWillMount() {
    let newProps = this.props;
    delete newProps.asyncHandler;
    this.setState({properties: newProps}):
  }

  render() {
    return <Button {...this.state.properties} />;
  }
}

这会将所有道具(带有spread operator)应用于&lt;Button /&gt;,除了asyncHandler,我们在安装组件之前通过在state中创建props的副本来删除它,但带有@ 987654334@ 已删除。

也检查this answer我给了一个类似的问题。

【讨论】:

    【解决方案2】:

    我刚刚遇到了这个问题。您可以只创建一个新元素并使用旧元素的类型和要传递的道具。我不确定这是否是反模式,我只是偶然发现它,到目前为止它似乎运行良好。

    它应该看起来像这样:

    function AsyncContainer(props) {
      const child = React.Children.only(props.children)
      const { asyncHandler, ...childProps } = child.props
      // do asyncHandler stuff
      return React.createElement(child.type, childProps)
    }
    

    【讨论】:

    • 这适用于许多情况,但有一个缺点。来自文档:reactjs.org/docs/react-api.html#cloneelement "... 它还保留了 refs。这意味着如果你得到一个带有 ref 的孩子,你不会不小心从你的祖先那里偷走它。你会得到相同的 ref 附加到你的新元素。”
    【解决方案3】:
    function AsyncContainer(props) {
      const child = React.Children.only(props.children);
      return React.cloneElement(
        child,
        { asyncHandler: undefined }
      );
    }
    

    工作原理

    1. 您使用React.cloneElement 克隆元素,因为元素是不可变的,更改其道具的唯一方法是创建克隆。
    2. 使用第二个React.cloneElement 参数添加新道具和删除旧道具。不需要的道具应该分配给undefined。您需要这样做,因为默认情况下克隆的元素会与其所有道具一起克隆。

    【讨论】:

    • 这样asyncHandler的props设置为undefined,但是如何从克隆的组件props中完全删除呢?
    • 你真的测试过这个吗?我认为您不能使用这样的未定义值来替换该函数。我建议看看React.createElement()
    猜你喜欢
    • 2020-07-17
    • 2016-03-19
    • 2019-11-24
    • 2018-02-07
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 2013-10-11
    • 1970-01-01
    相关资源
    最近更新 更多