Container Components and Presentational Components

When writing components with React, we need to consciously divide them into Container components and Presentational components. This helps us be more aware of what the component is responsible for when writing it.

The container component is responsible for processing business process logic, such as sending network requests, processing request data, and passing the processed data to the Props of the child components. At the same time, the container component provides the methods of source data and passes them to the sub-components in the way of Props. When the state change of the sub-component causes the changes of source data, the sub-component synchronizes the changes by calling the methods provided by the container component.

Presentation components, which are responsible for the appearance of components, that is, how they are rendered, are highly cohesive. A demonstrative component doesn’t care how the component properties (Props) used in rendering are obtained, it just needs to know how the component should be rendered with those Props. How properties are retrieved is the responsibility of container components. When a change in the state of a presentable component needs to be synchronized to the source data, a method in the container component needs to be called. This method is also passed to the presentable component via Props.

For example, a Todo project has a Todo component and a TodoList component. The Todo component is a container component that gets the to-do list from the server and passes it to TodoList for display. After creating a to-do item in TodoList, you need to invoke the method of saving the to-do item in the Todo component through TodoList Props to synchronize the new to-do item to the server.

Container components and presentation components can be nested with each other. A container component can contain multiple presentation components and other container components. A presentation group can also contain container components and other presentation components. This division of labor can make the logic that is not directly related to component rendering centralized by container components, while the presentation components only pay attention to the rendering logic of components, so that the presentation components are easier to reuse. For very simple pages, one container component is usually sufficient; But to be responsible for the page, you will need to more containers components, otherwise all the business logic in a container component processing, will cause the component is very complex, this component to get to the source data at the same time, may need Props of pass through many layers of components, used to reach the final display components.

Props, State, and general properties of the component

The concepts of Props and State are clear, and the generic properties of a component are properties that are mounted directly under this in the component. Props and State are also common properties of the component because we can get them directly from this. Props and this. State. When should Props, State, and other common component properties be used?

Both Props and State are used for component rendering. That is, what a component looks like depends on its Props and State. Changes to both Props and State trigger the render method of the component. But there is a difference. Props is read-only data, which is passed by the parent component; State is a self-maintained State within the component and is mutable. The State can change depending on the Props. If there are additional properties that are required in the component that are not related to the component’s rendering (i.e., not used in the render method), then the property can be attached directly to this rather than as a state of the component.

For example, if a component needs a timer and changes the state of the component every few seconds, you can define a this.timer property in case the timer is cleared when componentWillUnmount.

SetState asynchrony

React updates this. State and this.props can be updated asynchronously. React may merge multiple setState calls into a single state update for performance reasons. So, don’t rely on the values of this.props and this.state to calculate the next state. Here’s a code example from the official website:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});Copy the code

If you have to do this, you can use another setState method that takes a function as an argument, the first argument being the previous State and the second argument being the latest Props currently received. As follows:

// Correct
this.setState(function(prevState, props) {
  return {
    counter: prevState.counter + props.increment
  };
});Copy the code

After calling setState, this. State cannot be immediately used to obtain the latest state, because the state at this time is probably not updated, to ensure that the state obtained is the latest state, you can obtain this. State in componentDidUpdate. You can also use setStatesetState(stateChange, [callback]) with the callback function argument version. This. state in the callback function is guaranteed to be the latest state.

componentWillReceiveProps

This method is called when a component’s properties might change. This is possible because every time the parent render method is called, the child’s method is called (except when the child is first initialized), but not necessarily every time the child’s properties change. If the component’s State needs to change depending on the Props, then this method is the best place for this logic. For example, if the component’s State needs to be reset when Props changes, you can call this.setstate () in this method to reset the State. This. Need to pay attention to, in this method call setState () will not trigger a componentWillReceiveProps call again, also won’t cause the render method to trigger twice. In general, to receive the new Props will trigger a render, call this. SetState would trigger a render, but componentWillReceiveProps invokes the enclosing setState, React to originally need to render twice, Merge into one.

shouldComponentUpdate

This method is often used to optimize React performance. When shouldComponentUpdate returns false, the render method of the component is not triggered. Depending on the actual business scenario, you can determine whether the Render method needs to be triggered by comparing state or props in this method.

React provides a React.PureComponent that overwrites shouldComponentUpdate to shallow compare the props and state, and return true if they are inconsistent, to trigger the render method. The shallow comparison here means that only the first-level properties of the state and props are compared (using! ==), which satisfies the general usage scenario. If your component inherits the React.PureComponent, but setState is passed in as a modified state object, it will still satisfy the shallow comparison conditions without retriggering the render method, resulting in DOM and state inconsistencies. For example, state={books: [‘A’,’B’]}, in setState, use this.setState({name: This.state.books.push (‘C’)}) directly modifies the books object so that even though the books contents have been modified, the shallow comparison condition is still satisfied because the object reference has not changed and the render method is not triggered.

In general, shouldComponentUpdate should return the default true without too much of a problem. Although this may result in some unnecessary render methods being called, the Render method directly manipulates the virtual DOM and does not change the physical DOM as long as the virtual DOM does not change. JS is slow in modifying the entity DOM. As long as your Render method is not very complex, there is no performance overhead associated with calling the Render method more than once.

render

The component’s Render method is triggered every time the parent component’s Render method is called, or every time the component itself calls the setState method (provided shouldComponentUpdate uses the default behavior and always returns true). Will the entity DOM be recreated every time the component renders? The answer is, no!

React is faster than javascript libraries that manipulate the DOM directly because React abstracts a layer of virtual DOM on top of the physical DOM. The render method is used to render the virtual DOM. React compares the current virtual DOM structure with the previous one. React synchronizes the different content to the entity DOM. If the structure of the virtual DOM remains the same after two renders, no modification of the entity DOM will be triggered.

React is also fast because of its excellent Diff algorithm. The time complexity of the standard Diff algorithm for comparing two trees is O(n3). React reduces the time complexity of the Diff algorithm to nearly O(n) based on two assumptions that are very consistent with the actual scenario. The two assumptions are:

  1. If two components or elements are of different types, then they are completely different trees and there is no need to compare their child nodes. For example,

    and

    will produce two complete tree structures;

    children

    and

    children

    are also two completely different trees. In this case, the component is completely rebuilt, the old DOM node is destroyed, the component goes through componentWillUnmount(), then a new tree is created, and the component goes through componentWillMount() and componentDidMount().

  2. You can set the key property for a component or element, which identifies the component or element. Keys do not need to be globally unique, just unique between sibling components or elements. Keys are commonly used in collection (List) elements. Such as:

<ul>
<li key='a'>Book A</li>
<li key='b'>Book B</li>
</ul>Copy the code

When a record Book C is inserted in the first position,

<ul>
<li key='c'>Book C</li>
<li key='a'>Book A</li>
<li key='b'>Book B</li>
</ul>Copy the code

React knows that a new

  • element is added because of the key identifier. It creates a new
  • element and inserts it at the first position in the list. If the key is not set, React doesn’t know whether a new record is added, the original two records are completely replaced with the new three records, or some other more complex modification scenario. React needs to compare each record from top to bottom. In this way, the nodes are different each time. Therefore, the nodes need to be modified twice and then a new node needs to be added.
  • Another problem exposed here is that you should not use the index value of the element in the collection as the key, because if the order of the elements in the collection changes, a large number of keys may fail, resulting in a large number of modification operations.

    How do I send network requests

    In which lifecycle method of the component should we send a network request when we need to fetch data from the server? React notes that you can send network requests in componentDidMount, which is a general best practice. Some people also put the send network request in componentWillMount, and think that this method precedes the componentDidMount call, so it gets the data faster. In my opinion, this method is generally fine, but it can be problematic in some scenarios, such as when rendering on the Server side, componentWillMount is called twice, once on the Server side and once on the Client side. Refer to this article.