mheavers
mheavers

Reputation: 30158

how to pass ajax data down to components in react

I'm learning react, and have an application that used to work with static data stored in a javascript object. I am now loading that data via ajax using axios.

This works, and I am currently storing that data in the app's state, then passing it down to the components once the data is loaded, but the way I'm passing the data as a prop to each component doesn't feel right.

How can each component access the parent app's data without passing it as a prop to each component?

Here's my code

    class App extends Component {

  constructor(props) {
    super(props);
    this.state = {appData: {}};
  }

  componentDidMount() {
    axios.get('/data/appData.json')
    .then((result)=> {
      const thisData = result.data;
      this.setState({
        appData: result.data
      });
    })
  }

  componentWillUnmount() {
    this.serverRequest.abort();
  }

  render() {

    const theData = this.state.appData;
    if (Object.keys(theData).length > 0 && theData.constructor === Object){ //if the object is not empty
      return (
        <div className="App">
          <AppHeader appData={theData} />
          <AppMenu appData={theData} />
          <MainCarousel appData={theData} />
          <HomeDetails appData={theData} />
          <Model3D appData={theData} />
          <AppMaps appData={theData} />
          <AppContact appData={theData} />
        </div>
      );
    } else {
      return (
        <div className="App"></div>
      )
    }

  }
}

And a component that would use the data looks like:

function AppHeader(props) {
  return (
    <div className="App-header">
      <h2 className="App-title">{props.appData.copy.title}</h2>
      <h4 className="App-subtitle">{props.appData.copy.subtitle}</h4>
    </div>
  );
}

for a function, or

class MainCarousel extends Component {
  mixins: [Carousel.ControllerMixin];

  constructor(props) {
    super(props);
  }

  render() {
    const carouselItems = this.props.appData.carouselItems.map((carouselItem) =>
      <AppCarouselItem key={carouselItem.name.toLowerCase()} name={carouselItem.name} image={carouselItem.image} />
    );
    return (
      <div className="App-carousel">
        <Carousel autoplay={true} wrapAround={true}>
          {carouselItems}
        </Carousel>
      </div>
    );
  }
}

for a class.

Upvotes: 1

Views: 1341

Answers (1)

aaronw
aaronw

Reputation: 156

For your purposes what you are doing is completely acceptable, the only thing I would change is to split out the state into an object for each component. This will stop every component from updating each time you update a single one of them.

Where things get messy is when your child components are updating the parent's state. This is where a library like Flux or Redux comes in handy.

If you are just creating a simple app with static data keep sending state to your component as props.

Upvotes: 1

Related Questions