React Transferring Props except one
JavascriptReactjsJavascript 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>
);
}
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 } // ...
);