#1
Hello. I have the code:
class Component extends React.Component {
render() {
this.props.nested.prop = this.props.parse.nested.prop;
return <div>Component</div>;
}
componentDidMount() {
console.log(this.props.nested.prop);
}
}
Component.defaultProps = {
nested: {
prop: "default",
},
};
const obj1 = {
nested: {
prop: "obj1",
},
};
const obj2 = {
nested: {
prop: "obj2",
},
};
class Application extends React.Component {
render() {
return (
<div>
<Component parse={obj1} />
<Component parse={obj2} />
</div>
);
}
}
React.render(<Application />, document.getElementById("app"));
// console output:
// "obj2"
// "obj2"
Why do I get 1 variable reference for 2 separate components instead of 2 instances of nested.prop for every component? Why this.props saves only last setted value for all instances of the component after mounting? Is it a normal behavior? I think the correct behavior is having different property values for different instances.
P.S. I have tested this code here.
#2
jimfb has been answered:
"You are mutating the default prop that was passed in. The line this.props.nested.prop = this.props.parse.nested.prop; is illegal."
My next question:
How to pass nested properties without a manual mutation of props?
For example:
Component.defaultProps = {
nested: {
prop1: "default",
prop2: "default",
},
};
const props = {
nested: {
prop1: "value",
},
};
let component = <Component {...props} />;
Guide to the code above JSX spread attribute feature just override props.nested and I lose default nested properties. But it is not that I need.
How about to implements a recursive traversing of nested objects in stage of JSX spread attributes parsing?
Or Is there some useful pattern for this case?
#1
Hello. I have the code:
class Component extends React.Component {
render() {
this.props.nested.prop = this.props.parse.nested.prop;
return <div>Component</div>;
}
componentDidMount() {
console.log(this.props.nested.prop);
}
}
Component.defaultProps = {
nested: {
prop: "default",
},
};
const obj1 = {
nested: {
prop: "obj1",
},
};
const obj2 = {
nested: {
prop: "obj2",
},
};
class Application extends React.Component {
render() {
return (
<div>
<Component parse={obj1} />
<Component parse={obj2} />
</div>
);
}
}
React.render(<Application />, document.getElementById("app"));
// console output:
// "obj2"
// "obj2"
Why do I get 1 variable reference for 2 separate components instead of 2 instances of nested.prop for every component? Why this.props saves only last setted value for all instances of the component after mounting? Is it a normal behavior? I think the correct behavior is having different property values for different instances.
P.S. I have tested this code here.
#2
jimfb has been answered:
"You are mutating the default prop that was passed in. The line this.props.nested.prop = this.props.parse.nested.prop; is illegal."
My next question:
How to pass nested properties without a manual mutation of props?
For example:
Component.defaultProps = {
nested: {
prop1: "default",
prop2: "default",
},
};
const props = {
nested: {
prop1: "value",
},
};
let component = <Component {...props} />;
Guide to the code above JSX spread attribute feature just override props.nested and I lose default nested properties. But it is not that I need.
How about to implements a recursive traversing of nested objects in stage of JSX spread attributes parsing?
Or Is there some useful pattern for this case?
1 Answer
Reset to default 22This is actually a good question!
Short answer: you can't do deep merge with spread operator - it only does shallow merging. But you surely can write function that will do objects traversing and implements deep merging.
This actually leaves you 3 options:
1) Just don't do deep merge. If you have 2 level nested object you can do such simple thing:
const newNested = {...oldProps.nested, ...newProps.nested };
const finalProps = { ...oldProps, nested: newNested };
Shallow merging force you to say explicitly that you will have new value of nested property. Which is a good thing as it makes your code obvious. You can also try out runnable examples here.
2) You may use a library for immutable structures. F.e. immutable.js. With it your code will look pretty similar.
const oldProps = Immutable.fromJS({
nested:
{
prop1: "OldValue1",
prop2: "OldValue2",
}
});
const newProps = Immutable.fromJS({
nested:
{
prop1: "NewValue1",
}
});
const finalProps = oldProps.updateIn(['nested'], (oldNested)=>
oldNested.merge(newProps.get('nested'))
)
3) You may use deep merge: find some implementation in npm or write it yourself and you will have a code like this(again immutable.js as an example):
const finalProps = oldProps.mergeDeep(newProps);
You may want this in some cases, but such code makes update operation implicit and it rises a lot of problems which are listed greatly here
foo(a.nested.property)
? – Felix Kling Commented Mar 28, 2016 at 15:39