React - most efficient way to share data between components

1k views Asked by At

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:

  1. have Sis make its initial HTTP request in componentWillMount and fetch the value of uid 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.
  2. have Dad make an HTTP request that performs 1 combined query to return the data needed by both Bro and Sis and pass it down to each accordingly. As it stands right now, Dad does not always display Bro and Sis (depending on the route). 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 nesting Dad in something like Grandpa and letting Grandpa take care of the routing while Dad fetches the data for Bro and Sis.

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?

1

There are 1 answers

3
Brian Le On BEST ANSWER

First of all, you shouldn't be calling an HTTP request in componentWillMount(). Instead do so in componentDidMount() as stated in React docs

Your 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: