I have this kind of a setup:
// inside Parent.js
class Parent extends React.Component {
render() {
return { this.props.children }
}
}
// inside Child.js
class Child extends React.Component {
render() {
let message;
const greet = this.context.store.parentState.greet;
if(greet) message = 'Hello, world!';
return (
<div>
{ message }
</div>
)
}
}
Child.contextTypes = {
store: PropTypes.object.isRequired
}
// inside App.js
<Parent>
<Route path='/a-path' component={ Child } />
</Parent>
When Parent
receives new state through setState
, its render
method is called but the render
method in Child
is not called!
The reason I want to achieve that is because some logic in Child
is dependent on the state of Parent
.
If I pass the state of Parent
via context
like how the store
is passed and then access it in Child
via this.context.parentState
, this seems to be working and causing a call on Child
's render
method, I guess it's because we're receiving new context
.
Why is this? context
is great but is there a good way around this particular issue without needing context
?
If you are rendering components as children, which aren't components to Route, you can make use of React.cloneElement
with React.Children.map
like
// inside Parent.js
class Parent extends React.Component {
render() {
return React.Children.map(this.props.children, (child) =>
React.cloneElement(child, {parentState: this.state.parentState})
);
}
}
However if elements rendered as Children to Parent are Routes then either you need to make use of context or write a wrapper around Route
so that any extra props that the Route receives are passed on to the component
const RouteWrapper = ({exact, path, component: Component, anyOtherRouterProp, ...rest}) =>
<Route exact={exact} path={path} {...otherRouterProps} render={(props) => <Component {...props} {...rest} />} />
Where in the above case anyOtherRouterProp
are the props that are applicable to the Route
and needs to be destructured separately. After this you can make use of React.Children.map and React.cloneElement to pass on the props to children.
Although this is one such way, I would still recommend you to make use of context, specially with the introduction of new context API
which makes it extremely easy to implement
You can do like this....
// inside Parent.js
class Parent extends React.Component {
render() {
return (
<Child children={this.props.children} />
)
}
}
// inside Child.js
class Child extends React.Component {
render() {
let message;
const greet = this.context.store.parentState.greet;
if(greet) message = 'Hello, world!';
return (
<div>
{ message }
{ this.props.children }
</div>
)
}
}
Child.contextTypes = {
store: PropTypes.object.isRequired
}
// inside App.js
<Parent>
<Route path='/a-path' component={ Child } />
</Parent>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.