Movatterモバイル変換


[0]ホーム

URL:


We want to hear from you!Take our 2021 Community Survey!
This site is no longer updated.Go to react.dev

State and Lifecycle

These docs are old and won’t be updated. Go toreact.dev for the new React docs.

These new documentation pages teach modern React and include live examples:

This page introduces the concept of state and lifecycle in a React component. You can find adetailed component API reference here.

Consider the ticking clock example fromone of the previous sections. InRendering Elements, we have only learned one way to update the UI. We callroot.render() to change the rendered output:

const root= ReactDOM.createRoot(document.getElementById('root'));functiontick(){const element=(<div><h1>Hello, world!</h1><h2>It is{newDate().toLocaleTimeString()}.</h2></div>);  root.render(element);}setInterval(tick,1000);

Try it on CodePen

In this section, we will learn how to make theClock component truly reusable and encapsulated. It will set up its own timer and update itself every second.

We can start by encapsulating how the clock looks:

const root= ReactDOM.createRoot(document.getElementById('root'));functionClock(props){return(<div><h1>Hello, world!</h1><h2>It is{props.date.toLocaleTimeString()}.</h2></div>);}functiontick(){  root.render(<Clockdate={newDate()}/>);}setInterval(tick,1000);

Try it on CodePen

However, it misses a crucial requirement: the fact that theClock sets up a timer and updates the UI every second should be an implementation detail of theClock.

Ideally we want to write this once and have theClock update itself:

root.render(<Clock/>);

To implement this, we need to add “state” to theClock component.

State is similar to props, but it is private and fully controlled by the component.

Converting a Function to a Class

You can convert a function component likeClock to a class in five steps:

  1. Create anES6 class, with the same name, that extendsReact.Component.
  2. Add a single empty method to it calledrender().
  3. Move the body of the function into therender() method.
  4. Replaceprops withthis.props in therender() body.
  5. Delete the remaining empty function declaration.
classClockextendsReact.Component{render(){return(<div><h1>Hello, world!</h1><h2>It is{this.props.date.toLocaleTimeString()}.</h2></div>);}}

Try it on CodePen

Clock is now defined as a class rather than a function.

Therender method will be called each time an update happens, but as long as we render<Clock /> into the same DOM node, only a single instance of theClock class will be used. This lets us use additional features such as local state and lifecycle methods.

Adding Local State to a Class

We will move thedate from props to state in three steps:

  1. Replacethis.props.date withthis.state.date in therender() method:
classClockextendsReact.Component{render(){return(<div><h1>Hello, world!</h1><h2>It is{this.state.date.toLocaleTimeString()}.</h2></div>);}}
  1. Add aclass constructor that assigns the initialthis.state:
classClockextendsReact.Component{constructor(props){super(props);this.state={date:newDate()};}render(){return(<div><h1>Hello, world!</h1><h2>It is{this.state.date.toLocaleTimeString()}.</h2></div>);}}

Note how we passprops to the base constructor:

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

Class components should always call the base constructor withprops.

  1. Remove thedate prop from the<Clock /> element:
root.render(<Clock/>);

We will later add the timer code back to the component itself.

The result looks like this:

classClockextendsReact.Component{constructor(props){super(props);this.state={date:newDate()};}render(){return(<div><h1>Hello, world!</h1><h2>It is{this.state.date.toLocaleTimeString()}.</h2></div>);}}const root= ReactDOM.createRoot(document.getElementById('root'));root.render(<Clock/>);

Try it on CodePen

Next, we’ll make theClock set up its own timer and update itself every second.

Adding Lifecycle Methods to a Class

In applications with many components, it’s very important to free up resources taken by the components when they are destroyed.

We want toset up a timer whenever theClock is rendered to the DOM for the first time. This is called “mounting” in React.

We also want toclear that timer whenever the DOM produced by theClock is removed. This is called “unmounting” in React.

We can declare special methods on the component class to run some code when a component mounts and unmounts:

classClockextendsReact.Component{constructor(props){super(props);this.state={date:newDate()};}componentDidMount(){}componentWillUnmount(){}render(){return(<div><h1>Hello, world!</h1><h2>It is{this.state.date.toLocaleTimeString()}.</h2></div>);}}

These methods are called “lifecycle methods”.

ThecomponentDidMount() method runs after the component output has been rendered to the DOM. This is a good place to set up a timer:

componentDidMount(){this.timerID=setInterval(()=>this.tick(),1000);}

Note how we save the timer ID right onthis (this.timerID).

Whilethis.props is set up by React itself andthis.state has a special meaning, you are free to add additional fields to the class manually if you need to store something that doesn’t participate in the data flow (like a timer ID).

We will tear down the timer in thecomponentWillUnmount() lifecycle method:

componentWillUnmount(){clearInterval(this.timerID);}

Finally, we will implement a method calledtick() that theClock component will run every second.

It will usethis.setState() to schedule updates to the component local state:

classClockextendsReact.Component{constructor(props){super(props);this.state={date:newDate()};}componentDidMount(){this.timerID=setInterval(()=>this.tick(),1000);}componentWillUnmount(){clearInterval(this.timerID);}tick(){this.setState({date:newDate()});}render(){return(<div><h1>Hello, world!</h1><h2>It is{this.state.date.toLocaleTimeString()}.</h2></div>);}}const root= ReactDOM.createRoot(document.getElementById('root'));root.render(<Clock/>);

Try it on CodePen

Now the clock ticks every second.

Let’s quickly recap what’s going on and the order in which the methods are called:

  1. When<Clock /> is passed toroot.render(), React calls the constructor of theClock component. SinceClock needs to display the current time, it initializesthis.state with an object including the current time. We will later update this state.
  2. React then calls theClock component’srender() method. This is how React learns what should be displayed on the screen. React then updates the DOM to match theClock’s render output.
  3. When theClock output is inserted in the DOM, React calls thecomponentDidMount() lifecycle method. Inside it, theClock component asks the browser to set up a timer to call the component’stick() method once a second.
  4. Every second the browser calls thetick() method. Inside it, theClock component schedules a UI update by callingsetState() with an object containing the current time. Thanks to thesetState() call, React knows the state has changed, and calls therender() method again to learn what should be on the screen. This time,this.state.date in therender() method will be different, and so the render output will include the updated time. React updates the DOM accordingly.
  5. If theClock component is ever removed from the DOM, React calls thecomponentWillUnmount() lifecycle method so the timer is stopped.

Using State Correctly

There are three things you should know aboutsetState().

Do Not Modify State Directly

For example, this will not re-render a component:

// Wrongthis.state.comment='Hello';

Instead, usesetState():

// Correctthis.setState({comment:'Hello'});

The only place where you can assignthis.state is the constructor.

State Updates May Be Asynchronous

React may batch multiplesetState() calls into a single update for performance.

Becausethis.props andthis.state may be updated asynchronously, you should not rely on their values for calculating the next state.

For example, this code may fail to update the counter:

// Wrongthis.setState({counter:this.state.counter+this.props.increment,});

To fix it, use a second form ofsetState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument:

// Correctthis.setState((state, props)=>({counter: state.counter+ props.increment}));

We used anarrow function above, but it also works with regular functions:

// Correctthis.setState(function(state, props){return{counter: state.counter+ props.increment};});

State Updates are Merged

When you callsetState(), React merges the object you provide into the current state.

For example, your state may contain several independent variables:

constructor(props){super(props);this.state={posts:[],comments:[]};}

Then you can update them independently with separatesetState() calls:

componentDidMount(){fetchPosts().then(response=>{this.setState({posts: response.posts});});fetchComments().then(response=>{this.setState({comments: response.comments});});}

The merging is shallow, sothis.setState({comments}) leavesthis.state.posts intact, but completely replacesthis.state.comments.

The Data Flows Down

Neither parent nor child components can know if a certain component is stateful or stateless, and they shouldn’t care whether it is defined as a function or a class.

This is why state is often called local or encapsulated. It is not accessible to any component other than the one that owns and sets it.

A component may choose to pass its state down as props to its child components:

<FormattedDatedate={this.state.date}/>

TheFormattedDate component would receive thedate in its props and wouldn’t know whether it came from theClock’s state, from theClock’s props, or was typed by hand:

functionFormattedDate(props){return<h2>It is{props.date.toLocaleTimeString()}.</h2>;}

Try it on CodePen

This is commonly called a “top-down” or “unidirectional” data flow. Any state is always owned by some specific component, and any data or UI derived from that state can only affect components “below” them in the tree.

If you imagine a component tree as a waterfall of props, each component’s state is like an additional water source that joins it at an arbitrary point but also flows down.

To show that all components are truly isolated, we can create anApp component that renders three<Clock>s:

functionApp(){return(<div><Clock/><Clock/><Clock/></div>);}

Try it on CodePen

EachClock sets up its own timer and updates independently.

In React apps, whether a component is stateful or stateless is considered an implementation detail of the component that may change over time. You can use stateless components inside stateful components, and vice versa.

Is this page useful?Edit this page

[8]ページ先頭

©2009-2025 Movatter.jp