React Transferring Props except one

JavascriptReactjs

Javascript Problem Overview


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>);
}

Javascript Solutions


Solution 1 - Javascript

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 - Javascript

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 - Javascript

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 - Javascript

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.

Solution 5 - Javascript

The simplest way I found so far:

const obj = {
  a: '1',
  b: '2',
  c: '3'
}

const _obj = {
  ...obj,
  b: undefined
}

This will result in _obj having all the props except b

Solution 6 - Javascript

Try this:

function removeProps(obj, propsToRemove) {
   let newObj = {};
   Object.keys(obj).forEach(key => {
   if (propsToRemove.indexOf(key) === -1)
   newObj[key] = obj[key]
   })
   return newObj;
}

const obj = {nome: 'joao', tel: '123', cidade: 'goiania'}

const restObject = removeProps(obj, ['cidade', 'tel'])

console.log('restObject',restObject)

restObject
{
  nome:"joao"
}

Solution 7 - Javascript

I had this issue when extending Material UI. A component would emit a warning if an unknown property was passed at all. I solved it slightly differently by specifically deleting the properties I didn't want to pass:

const passableProps = { ...props } as Partial<typeof props>;
delete passableProps.customValidity;
return (
    <TextField { ...passableProps } // ...
);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAugustin RiedingerView Question on Stackoverflow
Solution 1 - JavascriptvilleakaView Answer on Stackoverflow
Solution 2 - JavascriptDan CarageaView Answer on Stackoverflow
Solution 3 - JavascriptJodoView Answer on Stackoverflow
Solution 4 - JavascriptPaul-SebastianView Answer on Stackoverflow
Solution 5 - JavascriptYonatan NaorView Answer on Stackoverflow
Solution 6 - JavascriptCleidson BarbosaView Answer on Stackoverflow
Solution 7 - JavascriptGeorgeView Answer on Stackoverflow