State and Lifecycle

Olivia·2022년 4월 21일
0
post-thumbnail

The Component Lifecycle

Each Class Component has several “lifecycle methods” that you can override to run code at particular times in the process.

A React component can go through four stages of its life as follows.

  • Initialization: This is the stage where the component is constructed with the given Props and default state. This is done in the constructor of a Component Class.
  • Mounting: Mounting is the stage of rendering the JSX returned by the render method itself.
  • Updating: Updating is the stage when the state of a component is updated and the application is repainted.
  • Unmounting: As the name suggests Unmounting is the final step of the component lifecycle where the component is removed from the page.

React provides the developers a set of predefined functions that if present is invoked around specific events in the lifetime of the component. Developers are supposed to override the functions with desired logic to execute accordingly.


Mounting

These methods are called in the following order when an instance of a component is being created and inserted into the DOM:

  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount()

constructor()

The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.

constructor(props) {
  super(props);
  // Don't call this.setState() here!
  this.state = { counter: 0 };
  this.handleClick = this.handleClick.bind(this);
}

getDerivedStateFromProps()

getDerivedStateFromProps() is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.
This method exists for rare use cases where the state depends on changes in props over time. For example, it might be handy for implementing a Transition component that compares its previous and next children to decide which of them to animate in and out.

static getDerivedStateFromProps(nextProps, prevState) {
    console.log("getDerivedStateFromProps");
    if (nextProps.color !== prevState.color) {
      return { color: nextProps.color };
    }
    return null;
  }

It requires static to be used in start and we can't recall this.

render()

The render() method is the only required method in a class component.

render()

The render() function should be pure, meaning that it does not modify component state, it returns the same result each time it’s invoked, and it does not directly interact with the browser.

componentDidMount()

componentDidMount() is invoked immediately after a component is mounted (inserted into the tree). Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.
When we call this method, the component we made already appeared on the screen. What we usually do in this stage is connecting to an external library which uses DOM like D3 and masonry or requesting ajax through axios and fetch to get needed data or reading and changing the attributes of DOM directly.


Updating

An update can be caused by changes to props or state. These methods are called in the following order when a component is being re-rendered:

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

getDerivedStateFromProps()

We already mentioned about it in Mounting.
If there is a change in props or state, then this method is called.

shouldComponentUpdate()

Use shouldComponentUpdate() to let React know if a component’s output is not affected by the current change in state or props. The default behavior is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior.
shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true. This method is not called for the initial render or when forceUpdate() is used.

shouldComponentUpdate(nextProps, nextState) {
    console.log("shouldComponentUpdate", nextProps, nextState);
    // if the last number is 4, then no rerendering
    return nextState.number % 10 !== 4;
  }

render()

we already mentioned!

getSnapshotBeforeUpdate()

getSnapshotBeforeUpdate() is invoked right before the most recently rendered output is committed to e.g. the DOM. It enables your component to capture some information from the DOM (e.g. scroll position) before it is potentially changed. Any value returned by this lifecycle method will be passed as a parameter to componentDidUpdate().
This use case is not common, but it may occur in UIs like a chat thread that need to handle scroll position in a special way.
A snapshot value (or null) should be returned.

getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log("getSnapshotBeforeUpdate");
    if (prevProps.color !== this.props.color) {
      return this.myRef.style.color;
    }
    return null;
  }

componentDidUpdate()

componentDidUpdate() is invoked immediately after updating occurs. This method is not called for the initial render.
Use this as an opportunity to operate on the DOM when the component has been updated. This is also a good place to do network requests as long as you compare the current props to previous props (e.g. a network request may not be necessary if the props have not changed).

componentDidUpdate(prevProps, prevState, snapshot) {
    console.log("componentDidUpdate", prevProps, prevState);
    if (snapshot) {
      console.log("color right before updating: ", snapshot);
    }
  }

getSnapshotBeforeUpdate()

getSnapshotBeforeUpdate() is invoked right before the most recently rendered output is committed to e.g. the DOM. It enables your component to capture some information from the DOM (e.g. scroll position) before it is potentially changed. Any value returned by this lifecycle method will be passed as a parameter to componentDidUpdate().
This use case is not common, but it may occur in UIs like a chat thread that need to handle scroll position in a special way.
A snapshot value (or null) should be returned.

getSnapshotBeforeUpdate(prevProps, prevState) {
    // It's right before DOM updating
    // to keep scrolling even new data is added on top
    // scrollHeight is to set the scroll's position
    // scrollTop is to stop this function
    // if it already exists
    if (prevState.array !== this.state.array) {
      const { scrollTop, scrollHeight } = this.list;

     // returning value will be given by componentDidMount as snapshot 
      return {
        scrollTop,
        scrollHeight
      };
    }
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    if (snapshot) {
      const { scrollTop } = this.list;
      if (scrollTop !== snapshot.scrollTop) return; // it this function already exists, then no need to work
      const diff = this.list.scrollHeight - snapshot.scrollHeight;
      this.list.scrollTop += diff;
    }
  }

Unmounting

This method is called when a component is being removed from the DOM:

  • componentWillUnmount()

componentWillUnmount()

componentWillUnmount() is invoked immediately before a component is unmounted and destroyed. Perform any necessary cleanup in this method, such as invalidating timers, canceling network requests, or cleaning up any subscriptions that were created in componentDidMount().
You should not call setState() in componentWillUnmount() because the component will never be re-rendered. Once a component instance is unmounted, it will never be mounted again.

componentWillUnmount() {
    console.log("componentWillUnmount");
  }

Error Handling

These methods are called when there is an error during rendering, in a lifecycle method, or in the constructor of any child component.

  • static getDerivedStateFromError()
  • componentDidCatch()

Sources
Official React Document:
https://reactjs.org/docs/react-component.html
Others:
https://www.geeksforgeeks.org/reactjs-lifecycle-components/
https://react.vlpt.us/basic/25-lifecycle.html

profile
No special aptitude, but persistent effort

0개의 댓글