Reputation: 46527
Say I have 3 props that my class based component requires and implements i.e.
<Component propOne={this.props.one} propTwo={this.props.two}>
{this.props.children}
</Component>
how would I pass down any other props that I originally don't expect, but say someone else using my component would want to use?
I was thinking
<Component propOne={this.props.one} propTwo={this.props.two} {...this.props} >
{this.props.children}
</Component>
But am concerned about prop duplication
Upvotes: 77
Views: 84541
Reputation: 1522
Here is how I do it:
export default function Button(props) {
const { children, label, ...rest } = props;
return (
<button
{...rest}
aria-label={label}
>
{children}
</button>
)
}
Just be aware sometimes you do not need attributes named the same as the given prop, so here I extracted label
and passed it to aria-label
.
Upvotes: 9
Reputation: 36289
Use spread syntax:
const {propOne, propTwo, ...leftOver} = this.props;
// `leftOver` contains everything except `propOne` and `propTwo`
So your example would become:
const { propOne, propTwo, children, ...props } = this.props;
<Component propOne={propOne} propTwo={propTwo} {...props}>
{children}
</Component>
Spread syntax (
...
) allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.
Source: MDN
Upvotes: 133
Reputation: 20948
The spread operator is great, but I was surprised I hadn't discovered it in the tutorials, and then it took forever to track down a reliable source describing it. In case you were doubting how it works, here are the details in the official ReactJS POD, from a little article called JSX In Depth...
If you already have props as an object, and you want to pass it in JSX, you can use ... as a “spread” operator to pass the whole props object. These two components are equivalent:
return <Greeting firstName="Ben" lastName="Hector" />; } function App2() { const props = {firstName: 'Ben', lastName: 'Hector'}; return <Greeting {...props} />; }```
And, of course, for your case, where you want to pass only some of the children...
const Button = props => { const { kind, ...other } = props; const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton"; return <button className={className} {...other} />; };
In the example above, the kind prop is safely consumed and is not passed on to the element in the DOM. All other props are passed via the ...other object making this component really flexible. You can see that it passes an onClick and children props.
Source: ReactJS.org: JSX In Depth, Specifying the React Element Type, Spread Attributes.
For your specific case...
const {propOne, propTwo, ...newChildProps} = this.props;
<Component
propOne={this.props.one}
propTwo={this.props.two}
{...newChildProps}
>{children}</Component>
Upvotes: 7
Reputation: 11
try to send whole properties as an Object under one property name. just like this
class ParentComponent extends Component{
state={
person:{
id=1,
name="rashid",
family="behnam"
}
}
render(){
return <ChildComponent wholething={this.state.person} />
}
}
//------------------------------------------
class ChildComponent extends Component{
render(){
const {id,name,family}=this.props.wholething;
return (
<div someId={id}>
<h3>My name is :{name}</h3>
<h4>My family is :{family}</h4>
</div>
);
}
}
Upvotes: 0
Reputation: 462
Filter them?
function without(props, keys) {
return Object.keys(props)
.filter((key) => keys.indexOf(key) !== -1)
.reduce((retVal, key) => {
retVal[key] = props[key];
}, {});
}
<Component propOne={this.props.one} propTwo={this.props.two} {...without(this.props, ['one', 'two'])} >
{this.props.children}
</Component>
Upvotes: 0