简体   繁体   中英

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.

AsyncContainer uses React.cloneElement(child, properties) .

I've tried nulling the asyncHandler property, setting it to undefined and deleting the property from the 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 /> :

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.


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.

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.
  2. Use second React.cloneElement argument to add new props and remove old props. Unneeded props should be assigned with undefined . You need to do this because by default cloned element is cloned with all its props.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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