Say I have
<ponent1>
<ponent2>
<ponent3>
<ponent4>
(where ponent1 has a child ponent2, ponent2 has a child ponent3, ponent3 has a child ponent4 )
and say I want to pass something from ponent1 into ponent4 . Do I need to pass props down the chain? so ponent1 -> ponent2 -> ponent3 -> ponent4
?
Please note:
these ponents are not in the same file. so in ponent1.js I refer to <ponent2>
and in ponent2.js I refer to <ponent3>
etc.
Say I have
<ponent1>
<ponent2>
<ponent3>
<ponent4>
(where ponent1 has a child ponent2, ponent2 has a child ponent3, ponent3 has a child ponent4 )
and say I want to pass something from ponent1 into ponent4 . Do I need to pass props down the chain? so ponent1 -> ponent2 -> ponent3 -> ponent4
?
Please note:
these ponents are not in the same file. so in ponent1.js I refer to <ponent2>
and in ponent2.js I refer to <ponent3>
etc.
- 1 Either that or use redux stores. – zero298 Commented Jan 8, 2018 at 19:57
-
control1
,control2
etc. are those ponents? – Nandu Kalidindi Commented Jan 8, 2018 at 20:00 - @NanduKalidindi yeah modified question – Shai UI Commented Jan 8, 2018 at 20:02
- so I need to use redux and actions and reducers just to pass some simple information? sigh.. – Shai UI Commented Jan 8, 2018 at 20:03
- 1 ponent1 cannot know anything about ponent4, so how is it supposed to pass something to it? You might have to rethink your architecture, but you are not providing enough information to offer any suggestion. – Felix Kling Commented Jan 8, 2018 at 20:06
3 Answers
Reset to default 9You have 2 main options here:
- Pass down the props.
- Use the
context
API
With props
you also got 2 main options:
You can pass the props implicit
<Parent> <ChildOne {...props}> <ChildTwo {...props}> </ChildTwo> </ChildOne> </Parent>
Running snippet for implicit props:
const ChildTwo = props => ( <div>{`Child two says: ${props.myProp}`}</div> ); const ChildOne = props => ( <div> <ChildTwo {...props} /> </div> ); const Parent = props => ( <div> <ChildOne {...props} /> </div> ); ReactDOM.render(<Parent myProp="hi there" />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div>
Or do it explicit
<Parent> <ChildOne propOne={propOne}> <ChildTwo propOne={propOne}> </ChildTwo> </ChildOne> </Parent>
Running snippet for explicit props:
const ChildTwo = (props) => (
<div>{`Child two says: ${props.myProp}`}</div>
);
const ChildOne = props => (
<div>
<ChildTwo myProp={props.myProp} />
</div>
);
const Parent = props => (
<div>
<ChildOne myProp={props.myProp} />
</div>
);
ReactDOM.render(<Parent myProp="hi there" />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
As for the context API, you can skip levels and "grab" props from grandparents.
This is what
react-redux
does behind the scenes.
Running example of the context API:
const ChildTwo = (props, context) => (
<div>{`Child two says: ${context.myProp}`}</div>
);
ChildTwo.contextTypes = { myProp: React.PropTypes.string }
const ChildOne = props => (
<div>
<ChildTwo />
</div>
);
class Parent extends React.Component {
getChildContext() {
const { myProp } = this.props;
return { myProp };
}
render() {
return (
<div>
<ChildOne />
</div>
);
}
}
Parent.childContextTypes = {
myProp: React.PropTypes.string
};
ReactDOM.render(<Parent myProp="hi there" />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Note that this example is using react v15, which the syntax for React.PropTypes
is changed, Since react v16 PropTypes
is no longer part of the react
library and it was extracted to another library prop-types
.
Also Note, that the docs advise against the usage of the context API:
If you aren’t an experienced React developer, don’t use context. There is usually a better way to implement functionality just using props and state.
You can use React's inbuilt Context API
, although I wouldn't suggest you rely too much on this because this either could get deprecated or be made into a full stable feature. As of now Facebook warns users with some points in their docs WARNING. Without that hiccup, the API is just wonderful and helps maintain neat code without having to send props all the way to the intended descendant.
CONTEXT API
COMPONENT 1
class Component1 extends React.Component {
getChildContext() {
return {
yourProp: "someValue" // you can also add a function like yourProp: someFunc
};
}
render() {
<Component2 />
}
}
Component1.childContextTypes = {
yourProp: PropTypes.string
};
COMPONENT 2
class Component2 extends React.Component {
render() {
return (
<Component3 />
);
}
}
COMPONENT 3
class Component3 extends React.Component {
render() {
return (
<Component4 />
);
}
}
COMPONENT4
class Component4 extends React.Component {
render() {
return (
<div>
{this.context.yourProp}
</div>
);
}
}
Component4.contextTypes = {
yourProp: PropTypes.string
};
There are quite many strategies if you don't choose to use this.
- REDUX
- EVENT EMITTER
- PASSING PROPS ALL THE WAY TO THE DESCENDANT
Yes with using just React you would need to pass down props through each ponent, even if the ponent doesn't use that prop. So in your example control2 & control3 don't care about the prop but need to pass it down. Below is what you would need to do.
<Control1 test={this.state.test}>
<Control2 test={this.props.test}>
<Control3 test={this.props.test}>
<Control4 test={this.props.test} />
</Control3>
</Control2>
</Control1>
This can get cumbersome so this is a case where redux can help.