简体   繁体   English

反应-从孩子身上移除道具

[英]React - Remove prop from child

I need to remove a prop from a child. 我需要从孩子身上移除道具。

I have a container element which uses a property on it's children to perform some enhancements on the children. 我有一个容器元素,该元素使用子元素上的属性对子元素进行一些增强。 That property should be removed from the child before rendering. 在渲染之前,应从子级中删除该属性。

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

The asyncHandler property should be removed from the button before rendering. 呈现之前,应从按钮中删除asyncHandler属性。

AsyncContainer uses React.cloneElement(child, properties) . AsyncContainer使用React.cloneElement(child, properties)

I've tried nulling the asyncHandler property, setting it to undefined and deleting the property from the child.props. 我尝试将asyncHandler属性设置为空,将其设置为undefined,然后从child.props中删除该属性。 It seems that it is impossible to get rid of this property again. 似乎不可能再次摆脱此属性。

I just ran into this issue. 我刚遇到这个问题。 You can just create a new element and use the old element's type and props you want to pass through. 您可以只创建一个新元素,并使用旧元素的类型和要传递的道具。 I'm not sure if this an anti-pattern or not, I just stumbled on it and it seems to be working well so far. 我不确定这是否是反模式,我偶然发现了它,到目前为止它似乎运行良好。

It should look something like this: 它看起来应该像这样:

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

As per the comments you cannot modify the props directly as they are immutable. 根据评论,您不能直接修改道具,因为它们是不可变的。

However, I think I have a simple solution to this problem. 但是,我认为我对此问题有一个简单的解决方案。 I have no idea what library that is or how it works, so this may or may not work . 我不知道它是什么库或它是如何工作的,所以这可能会或可能不会 However, this is a general answer to how you would remove a prop before a component gets mounted. 但是,这是在安装组件之前如何移除支撑的一般答案。

That being said, I would try to create my own component which renders a <Button /> : 话虽如此,我会尝试创建自己的呈现<Button />的组件:

class MyButtonComponent extends React.Component {

...

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

Then in the component you want to do your enhancements: 然后在组件中进行增强:

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

This way you maintain your onClick eventlistener on the <Button /> component but you don't pass the illegal asyncHandler prop. 这样,您可以在<Button />组件上维护onClick asyncHandler但不会传递非法的asyncHandler


Edit: 编辑:

Alternatively, you could also do: 或者,您也可以执行以下操作:

class MyButtonComponent extends React.Component {

...

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

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

This will apply all the props (with the spread operator ) to <Button /> except for asyncHandler which we delete prior to the component being mounted by creating a copy of the props in state but with asyncHandler removed. 这会将所有道具(使用spread操作符 )应用于<Button />asyncHandler除外,我们通过在state下创建props的副本但移除了asyncHandler方式在组件安装之前将其删除。

Also check this answer I gave to a similar question. 还要检查我给类似问题的答案

function AsyncContainer(props) {
  const child = React.Children.only(props.children);
  return React.cloneElement(
    child,
    { asyncHandler: undefined }
  );
}

How it works 这个怎么运作

  1. You clone element using React.cloneElement because element is immutable and only way to change its props is to create clone. 您使用React.cloneElement克隆元素,因为element是不可变的,更改道具的唯一方法是创建克隆。
  2. Use second React.cloneElement argument to add new props and remove old props. 使用第二个React.cloneElement参数添加新道具并删除旧道具。 Unneeded props should be assigned with undefined . 不需要的道具应该分配undefined You need to do this because by default cloned element is cloned with all its props. 您需要执行此操作,因为默认情况下,cloned元素会与其所有props一起被克隆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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