官术网_书友最值得收藏!

Container components

In this final section of the chapter, we're going to cover the concept of container components. This is a common React pattern, and it brings together many of the concepts that you've learned about state and properties.

The basic premise of container components is simple: don't couple data fetching with the component that renders the data. The container is responsible for fetching the data and passing it to its child component. It contains the component responsible for rendering the data.

The idea is that you should be able to achieve some level of substitutability with this pattern. For example, a container could substitute its child component. Or, a child component could be used in a different container. Let's see the container pattern in action, starting with the container itself:

import React, { Component } from 'react'; 
 
import MyList from './MyList'; 
 
// Utility function that's intended to mock 
// a service that this component uses to 
// fetch it's data. It returns a promise, just 
// like a real async API call would. In this case, 
// the data is resolved after a 2 second delay. 
function fetchData() { 
  return new Promise((resolve) => { 
    setTimeout(() => { 
      resolve([ 
        'First', 
        'Second', 
        'Third', 
      ]); 
    }, 2000); 
  }); 
} 
 
// Container components usually have state, so they 
// can't be declared as functions. 
export default class MyContainer extends Component { 
 
  // The container should always have an initial state, 
  // since this will be passed down to child components 
  // as properties. 
  state = { items: [] } 
 
  // After the component has been rendered, make the 
  // call to fetch the component data, and change the 
  // state when the data arrives. 
  componentDidMount() { 
    fetchData() 
      .then(items => this.setState({ items })); 
  } 
 
  // Renders the containee, passing the container 
  // state as properties, using the spread operator: "...". 
  render() { 
    return ( 
      <MyList {...this.state} /> 
    ); 
  } 
} 

The job of this component is to fetch data and to set its state. Any time the state is set, render() is called. This is where the child component comes in. The state of the container is passed to the child as properties. Let's take a look at the MyList component next:

import React from 'react'; 
 
// A stateless component that expects 
// an "items" property so that it can render 
// a "<ul>" element. 
export default ({ items }) => ( 
  <ul> 
    {items.map(i => ( 
      <li key={i}>{i}</li> 
    ))} 
  </ul> 
); 

Nothing much to it; a simple functional component that expects an items property. Let's see how the container component is actually used:

import React from 'react'; 
import { render } from 'react-dom'; 
 
import MyContainer from './MyContainer'; 
 
// All we have to do is render the "MyContainer" 
// component, since it looks after providing props 
// for it's children. 
render( 
  (<MyContainer />), 
  document.getElementById('app') 
); 

We'll go into more depth on container component design in Chapter 5, Crafting Reusable Components. The idea of this example was to give you a feel for the interplay between state and properties in React components.

When you load the page, you'll see the following content rendered after the 3 seconds it takes to simulate an HTTP request:

主站蜘蛛池模板: 庄河市| 密山市| 海伦市| 巨野县| 武义县| 武鸣县| 中江县| 永嘉县| 南通市| 灯塔市| 顺昌县| 大城县| 聂拉木县| 黄大仙区| 微山县| 方山县| 张北县| 南溪县| 龙游县| 临夏县| 金沙县| 信阳市| 大兴区| 安多县| 旌德县| 大荔县| 青岛市| 体育| 健康| 上林县| 三河市| 通山县| 稻城县| 桦甸市| 乳山市| 子长县| 葵青区| 含山县| 岱山县| 金山区| 象山县|