React Transferring Props except one

React suggests to Transfer Props. Neat!

How can I transfert all but one?

render: function(){
  return (<Cpnt {...this.propsButOne}><Subcpnt one={this.props.one} /></Cpnt>);
}

Solution 1:

You can use the following technique to consume some of the props and pass on the rest:

render() {
  var {one, ...other} = this.props;
  return (
    <Cpnt {...other}>
      <Subcpnt one={one} />
    </Cpnt>
  );
}

Source

Solution 2:

What you need to do is to create a copy of the props object and delete the key(s) you don't want. The easiest would be to use omit from lodash but you could also write a bit of code for this (create a new object that has all the keys of props except for one).

With omit (a few options at the top, depending on what package you import/ES flavor you use):

const omit = require('lodash.omit');
//const omit = require('lodash/omit');
//import { omit } from 'lodash';

...
render() {
    const newProps = omit(this.props, 'one');
    return <Cpnt {...newProps}><Subcpnt one={this.props.one} /></Cpnt>;
}

Solution 3:

If you have a lot of props you don't want in ...rest e.g. defaultProps, it can be annoying to write all of them twice. Instead you can create it yourself with a simple loop over the current props like that:

let rest = {};
Object.keys(this.props).forEach((key, index) => {
    if(!(key in MyComponent.defaultProps))
       rest[key] = this.props[key];
});

Solution 4:

Thank you @villeaka!

Here's an example of how I used your solution for other people to better understand it's usage.

I basically used it to create a stateless wrapping-component that I then needed to pass its props to the inner component (Card).

I needed the wrapper because of the rendering logic inside another top level component that used this wrapper like this:

<TopLevelComponent>
  {/* if condition render this: */}
  <CardWrapper {...props}> {/* note: props here is TLC's props */}
    <Card {..propsExceptChildren}>
      {props.children}
    </Card>
  </CardWrapper>
  {/* if other condition render this: */}
  {/* ... */}
  {/* and repeat */}
</TopLevelComponent>

where several conditions determine what comes after the H4 in the wrapper (see actual rendered node tree below).

So basically, I didn't want to duplicate code by writing the entire part that comes before {children} in the example below, for each arm of the conditional in the top level component that renders multiple variants of the wrapper from above example:

const CardWrapper: React.FC<IRecentRequestsCardProps> = (props) => {
  const { children, ...otherProps } = props;
  return (
    <Card {...otherProps} interactive={false} elevation={Elevation.ONE}>
      <H4>
        <a href="/">Unanswered requests</a>
      </H4>
      {children}
    </Card>
  );
};

And concrete usage in a React render function:

if (error)
  return (
    <CardWrapper {...props}>
      <SimpleAlert title="Eroare" intent={Intent.DANGER}>
        {error}
      </SimpleAlert>
    </CardWrapper>
  );

if (loading)
  return (
    <CardWrapper {...props}>
      <NonIdealState
        icon="download"
        title="Vă rog așteptați!"
        description="Se încarcă cererile pentru articole..."
      />
    </CardWrapper>
  );

if (!data)
  return (
    <CardWrapper {...props}>
      <NonIdealState
        icon="warning-sign"
        title="Felicitări!"
        description="Nu există cereri fără răspuns."
      />
    </CardWrapper>
  );

// etc.

So the above just adds the H4 header before the children of the wrapper and also passes down the props that it has been passed down to, to the inner Card component.