I'll start by saying I'm very new to React and am just playing around with having components interact with each other... trying to get a sense for where state
belongs and the most efficient way(s) to render changes on screen.
I have 2 sibling components, Bro
and Sis
that are direct children of Dad
. Bro
makes an HTTP request in componentWillMount
to get initial values for its state
. It then passes one of the pieces of data from the response (uid
) back up to Dad
(via a method defined in Dad
) which is then passed down to Sis
via props
. Sis
then uses this value in making ITS initial HTTP request (in componentDidUpdate
) to populate ITS state
.
Dad
class Dad extends Component {
state = {
uid: null
}
updateUID = id => {
this.setState({uid: id});
}
}
render() {
return (
<>
<Bro />
<Sis update={this.updateUID} />
</>
);
}
Sis
class Sis extends Component {
state = {
uid: null,
something: null,
another: null
}
componentDidUpdate() {
axios.get('example.com/endpoint2.json')
.then(res => {
/*
transform as needed and put the vales from
res.data into this.state accordingly...
*/
});
}
render () {
return <section>Component: Sis</section>;
}
}
Bro
class Bro extends Component {
state = {
uid: null,
blah: null,
blah-blah: null
}
componentWillUpdate() {
axios.get('example.com/endpoint1.json')
.then(res => {
/*
...
transform as needed and put the vales from
res.data into this.state accordingly...
*/
// pass uid back up to Dad to be passed down to Sis
this.props.update(res.data.uid);
});
}
render () {
return <section>Component: Bro</section>;
}
}
Is this Bro
--> Dad
--> Sis
passing of data the right way to do this? This seems a bit slow and perhaps unnecessarily complicated to me... I think. The alternate ways i can think of doing it are:
- have
Sis
make its initial HTTP request incomponentWillMount
and fetch the value ofuid
on its own. This would eliminate the need to pass it from one child to the parent to the other child, but it would involve a partially redundant query on the backend which is why I chose not to go this route. - have
Dad
make an HTTP request that performs 1 combined query to return the data needed by bothBro
andSis
and pass it down to each accordingly. As it stands right now,Dad
does not always displayBro
andSis
(depending on theroute
). In those cases, it would be a useless HTTP request and thus definitely not right, but I'm thinking a bit of restructuring may make this viable... perhaps nestingDad
in something likeGrandpa
and lettingGrandpa
take care of the routing whileDad
fetches the data forBro
andSis
.
So I guess ultimately my question is: should I be passing data between child/adjacent/sibling components via their parent component or should the parent component be the source of the data for both children and pass it down to each accordingly?
First of all, you shouldn't be calling an HTTP request in
componentWillMount()
. Instead do so incomponentDidMount()
as stated in React docsYour method is complete fine. However based on the container/presentational (smart/dump) components strategy you'd better do all your data fetching in
<Dad />
component, then pass down the required data to the children. This way it would be so much easier to keep track of your requests and your data won't be scattered about.An alternative is to use 3rd-party libraries such as Redux or Mobx State Tree. I'm not sure about Mobx, but what Redux does is it keeps the state outside of the components and make it available to the whole application by React context. You should be thinking about using this as it's extremely powerful and easy to learn
Last but no least, I will include a couple of posts here about container/presentational components pattern: