Pitfall
We recommend defining components as functions instead of classes.See how to migrate.
Component is the base class for the React components defined asJavaScript classes. Class components are still supported by React, but we don’t recommend using them in new code.
class GreetingextendsComponent{
render(){
return<h1>Hello,{this.props.name}!</h1>;
}
}- Reference
Componentcontextpropsrefsstateconstructor(props)componentDidCatch(error, info)componentDidMount()componentDidUpdate(prevProps, prevState, snapshot?)componentWillMount()componentWillReceiveProps(nextProps)componentWillUpdate(nextProps, nextState)componentWillUnmount()forceUpdate(callback?)getChildContext()getSnapshotBeforeUpdate(prevProps, prevState)render()setState(nextState, callback?)shouldComponentUpdate(nextProps, nextState, nextContext)UNSAFE_componentWillMount()UNSAFE_componentWillReceiveProps(nextProps, nextContext)UNSAFE_componentWillUpdate(nextProps, nextState)static childContextTypesstatic contextTypesstatic contextTypestatic defaultPropsstatic propTypesstatic getDerivedStateFromError(error)static getDerivedStateFromProps(props, state)
- Usage
- Alternatives
Reference
Component
To define a React component as a class, extend the built-inComponent class and define arender method:
import{Component}from'react';
class GreetingextendsComponent{
render(){
return<h1>Hello,{this.props.name}!</h1>;
}
}Only therender method is required, other methods are optional.
context
Thecontext of a class component is available asthis.context. It is only available if you specifywhich context you want to receive usingstatic contextType (modern) orstatic contextTypes (deprecated).
A class component can only read one context at a time.
class ButtonextendsComponent{
staticcontextType =ThemeContext;
render(){
consttheme =this.context;
constclassName ='button-' +theme;
return(
<buttonclassName={className}>
{this.props.children}
</button>
);
}
}Note
Readingthis.context in class components is equivalent touseContext in function components.
props
The props passed to a class component are available asthis.props.
class GreetingextendsComponent{
render(){
return<h1>Hello,{this.props.name}!</h1>;
}
}
<Greetingname="Taylor"/>Note
Readingthis.props in class components is equivalent todeclaring props in function components.
refs
Deprecated
This API will be removed in a future major version of React.UsecreateRef instead.
Lets you accesslegacy string refs for this component.
state
The state of a class component is available asthis.state. Thestate field must be an object. Do not mutate the state directly. If you wish to change the state, callsetState with the new state.
class CounterextendsComponent{
state ={
age:42,
};
handleAgeChange =()=>{
this.setState({
age:this.state.age +1
});
};
render(){
return(
<>
<buttononClick={this.handleAgeChange}>
Increment age
</button>
<p>You are{this.state.age}.</p>
</>
);
}
}Note
Definingstate in class components is equivalent to callinguseState in function components.
constructor(props)
Theconstructor runs before your class componentmounts (gets added to the screen). Typically, a constructor is only used for two purposes in React. It lets you declare state andbind your class methods to the class instance:
class CounterextendsComponent{
constructor(props){
super(props);
this.state ={counter:0};
this.handleClick =this.handleClick.bind(this);
}
handleClick(){
// ...
}If you use modern JavaScript syntax, constructors are rarely needed. Instead, you can rewrite this code above using thepublic class field syntax which is supported both by modern browsers and tools likeBabel:
class CounterextendsComponent{
state ={counter:0};
handleClick =()=>{
// ...
}A constructor should not contain any side effects or subscriptions.
Parameters
props: The component’s initial props.
Returns
constructor should not return anything.
Caveats
Do not run any side effects or subscriptions in the constructor. Instead, use
componentDidMountfor that.Inside a constructor, you need to call
super(props)before any other statement. If you don’t do that,this.propswill beundefinedwhile the constructor runs, which can be confusing and cause bugs.Constructor is the only place where you can assign
this.statedirectly. In all other methods, you need to usethis.setState()instead. Do not callsetStatein the constructor.When you useserver rendering, the constructor will run on the server too, followed by the
rendermethod. However, lifecycle methods likecomponentDidMountorcomponentWillUnmountwill not run on the server.WhenStrict Mode is on, React will call
constructortwice in development and then throw away one of the instances. This helps you notice the accidental side effects that need to be moved out of theconstructor.
Note
There is no exact equivalent forconstructor in function components. To declare state in a function component, calluseState. To avoid recalculating the initial state,pass a function touseState.
componentDidCatch(error, info)
If you definecomponentDidCatch, React will call it when some child component (including distant children) throws an error during rendering. This lets you log that error to an error reporting service in production.
Typically, it is used together withstatic getDerivedStateFromError which lets you update state in response to an error and display an error message to the user. A component with these methods is called anerror boundary.
Parameters
error: The error that was thrown. In practice, it will usually be an instance ofErrorbut this is not guaranteed because JavaScript allows tothrowany value, including strings or evennull.info: An object containing additional information about the error. ItscomponentStackfield contains a stack trace with the component that threw, as well as the names and source locations of all its parent components. In production, the component names will be minified. If you set up production error reporting, you can decode the component stack using sourcemaps the same way as you would do for regular JavaScript error stacks.
Returns
componentDidCatch should not return anything.
Caveats
In the past, it was common to call
setStateinsidecomponentDidCatchin order to update the UI and display the fallback error message. This is deprecated in favor of definingstatic getDerivedStateFromError.Production and development builds of React slightly differ in the way
componentDidCatchhandles errors. In development, the errors will bubble up towindow, which means that anywindow.onerrororwindow.addEventListener('error', callback)will intercept the errors that have been caught bycomponentDidCatch. In production, instead, the errors will not bubble up, which means any ancestor error handler will only receive errors not explicitly caught bycomponentDidCatch.
Note
There is no direct equivalent forcomponentDidCatch in function components yet. If you’d like to avoid creating class components, write a singleErrorBoundary component like above and use it throughout your app. Alternatively, you can use thereact-error-boundary package which does that for you.
componentDidMount()
If you define thecomponentDidMount method, React will call it when your component is added(mounted) to the screen. This is a common place to start data fetching, set up subscriptions, or manipulate the DOM nodes.
If you implementcomponentDidMount, you usually need to implement other lifecycle methods to avoid bugs. For example, ifcomponentDidMount reads some state or props, you also have to implementcomponentDidUpdate to handle their changes, andcomponentWillUnmount to clean up whatevercomponentDidMount was doing.
class ChatRoomextendsComponent{
state ={
serverUrl:'https://localhost:1234'
};
componentDidMount(){
this.setupConnection();
}
componentDidUpdate(prevProps,prevState){
if(
this.props.roomId !==prevProps.roomId ||
this.state.serverUrl !==prevState.serverUrl
){
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount(){
this.destroyConnection();
}
// ...
}Parameters
componentDidMount does not take any parameters.
Returns
componentDidMount should not return anything.
Caveats
WhenStrict Mode is on, in development React will call
componentDidMount, then immediately callcomponentWillUnmount, and then callcomponentDidMountagain. This helps you notice if you forgot to implementcomponentWillUnmountor if its logic doesn’t fully “mirror” whatcomponentDidMountdoes.Although you may call
setStateimmediately incomponentDidMount, it’s best to avoid that when you can. It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though therenderwill be called twice in this case, the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. In most cases, you should be able to assign the initial state in theconstructorinstead. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.
Note
For many use cases, definingcomponentDidMount,componentDidUpdate, andcomponentWillUnmount together in class components is equivalent to callinguseEffect in function components. In the rare cases where it’s important for the code to run before browser paint,useLayoutEffect is a closer match.
componentDidUpdate(prevProps, prevState, snapshot?)
If you define thecomponentDidUpdate method, React will call it immediately after your component has been re-rendered with updated props or state. This method is not called for the initial render.
You can use it to manipulate the DOM after an update. This is also a common 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). Typically, you’d use it together withcomponentDidMount andcomponentWillUnmount:
class ChatRoomextendsComponent{
state ={
serverUrl:'https://localhost:1234'
};
componentDidMount(){
this.setupConnection();
}
componentDidUpdate(prevProps,prevState){
if(
this.props.roomId !==prevProps.roomId ||
this.state.serverUrl !==prevState.serverUrl
){
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount(){
this.destroyConnection();
}
// ...
}Parameters
prevProps: Props before the update. CompareprevPropstothis.propsto determine what changed.prevState: State before the update. CompareprevStatetothis.stateto determine what changed.snapshot: If you implementedgetSnapshotBeforeUpdate,snapshotwill contain the value you returned from that method. Otherwise, it will beundefined.
Returns
componentDidUpdate should not return anything.
Caveats
componentDidUpdatewill not get called ifshouldComponentUpdateis defined and returnsfalse.The logic inside
componentDidUpdateshould usually be wrapped in conditions comparingthis.propswithprevProps, andthis.statewithprevState. Otherwise, there’s a risk of creating infinite loops.Although you may call
setStateimmediately incomponentDidUpdate, it’s best to avoid that when you can. It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though therenderwill be called twice in this case, the user won’t see the intermediate state. This pattern often causes performance issues, but it may be necessary for rare cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.
Note
For many use cases, definingcomponentDidMount,componentDidUpdate, andcomponentWillUnmount together in class components is equivalent to callinguseEffect in function components. In the rare cases where it’s important for the code to run before browser paint,useLayoutEffect is a closer match.
componentWillMount()
Deprecated
This API has been renamed fromcomponentWillMount toUNSAFE_componentWillMount. The old name has been deprecated. In a future major version of React, only the new name will work.
Run therename-unsafe-lifecycles codemod to automatically update your components.
componentWillReceiveProps(nextProps)
Deprecated
This API has been renamed fromcomponentWillReceiveProps toUNSAFE_componentWillReceiveProps. The old name has been deprecated. In a future major version of React, only the new name will work.
Run therename-unsafe-lifecycles codemod to automatically update your components.
componentWillUpdate(nextProps, nextState)
Deprecated
This API has been renamed fromcomponentWillUpdate toUNSAFE_componentWillUpdate. The old name has been deprecated. In a future major version of React, only the new name will work.
Run therename-unsafe-lifecycles codemod to automatically update your components.
componentWillUnmount()
If you define thecomponentWillUnmount method, React will call it before your component is removed(unmounted) from the screen. This is a common place to cancel data fetching or remove subscriptions.
The logic insidecomponentWillUnmount should “mirror” the logic insidecomponentDidMount. For example, ifcomponentDidMount sets up a subscription,componentWillUnmount should clean up that subscription. If the cleanup logic in yourcomponentWillUnmount reads some props or state, you will usually also need to implementcomponentDidUpdate to clean up resources (such as subscriptions) corresponding to the old props and state.
class ChatRoomextendsComponent{
state ={
serverUrl:'https://localhost:1234'
};
componentDidMount(){
this.setupConnection();
}
componentDidUpdate(prevProps,prevState){
if(
this.props.roomId !==prevProps.roomId ||
this.state.serverUrl !==prevState.serverUrl
){
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount(){
this.destroyConnection();
}
// ...
}Parameters
componentWillUnmount does not take any parameters.
Returns
componentWillUnmount should not return anything.
Caveats
- WhenStrict Mode is on, in development React will call
componentDidMount, then immediately callcomponentWillUnmount, and then callcomponentDidMountagain. This helps you notice if you forgot to implementcomponentWillUnmountor if its logic doesn’t fully “mirror” whatcomponentDidMountdoes.
Note
For many use cases, definingcomponentDidMount,componentDidUpdate, andcomponentWillUnmount together in class components is equivalent to callinguseEffect in function components. In the rare cases where it’s important for the code to run before browser paint,useLayoutEffect is a closer match.
forceUpdate(callback?)
Forces a component to re-render.
Usually, this is not necessary. If your component’srender method only reads fromthis.props,this.state, orthis.context, it will re-render automatically when you callsetState inside your component or one of its parents. However, if your component’srender method reads directly from an external data source, you have to tell React to update the user interface when that data source changes. That’s whatforceUpdate lets you do.
Try to avoid all uses offorceUpdate and only read fromthis.props andthis.state inrender.
Parameters
- optional
callbackIf specified, React will call thecallbackyou’ve provided after the update is committed.
Returns
forceUpdate does not return anything.
Caveats
- If you call
forceUpdate, React will re-render without callingshouldComponentUpdate.
Note
Reading an external data source and forcing class components to re-render in response to its changes withforceUpdate has been superseded byuseSyncExternalStore in function components.
getChildContext()
Deprecated
This API will be removed in a future major version of React.UseContext.Provider instead.
Lets you specify the values for thelegacy context is provided by this component.
getSnapshotBeforeUpdate(prevProps, prevState)
If you implementgetSnapshotBeforeUpdate, React will call it immediately before React updates 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 tocomponentDidUpdate.
For example, you can use it in a UI like a chat thread that needs to preserve its scroll position during updates:
class ScrollingListextendsReact.Component{
constructor(props){
super(props);
this.listRef =React.createRef();
}
getSnapshotBeforeUpdate(prevProps,prevState){
// Are we adding new items to the list?
// Capture the scroll position so we can adjust scroll later.
if(prevProps.list.length <this.props.list.length){
constlist =this.listRef.current;
returnlist.scrollHeight -list.scrollTop;
}
returnnull;
}
componentDidUpdate(prevProps,prevState,snapshot){
// If we have a snapshot value, we've just added new items.
// Adjust scroll so these new items don't push the old ones out of view.
// (snapshot here is the value returned from getSnapshotBeforeUpdate)
if(snapshot !==null){
constlist =this.listRef.current;
list.scrollTop =list.scrollHeight -snapshot;
}
}
render(){
return(
<divref={this.listRef}>{/* ...contents... */}</div>
);
}
}In the above example, it is important to read thescrollHeight property directly ingetSnapshotBeforeUpdate. It is not safe to read it inrender,UNSAFE_componentWillReceiveProps, orUNSAFE_componentWillUpdate because there is a potential time gap between these methods getting called and React updating the DOM.
Parameters
prevProps: Props before the update. CompareprevPropstothis.propsto determine what changed.prevState: State before the update. CompareprevStatetothis.stateto determine what changed.
Returns
You should return a snapshot value of any type that you’d like, ornull. The value you returned will be passed as the third argument tocomponentDidUpdate.
Caveats
getSnapshotBeforeUpdatewill not get called ifshouldComponentUpdateis defined and returnsfalse.
Note
At the moment, there is no equivalent togetSnapshotBeforeUpdate for function components. This use case is very uncommon, but if you have the need for it, for now you’ll have to write a class component.
render()
Therender method is the only required method in a class component.
Therender method should specify what you want to appear on the screen, for example:
import{Component}from'react';
class GreetingextendsComponent{
render(){
return<h1>Hello,{this.props.name}!</h1>;
}
}React may callrender at any moment, so you shouldn’t assume that it runs at a particular time. Usually, therender method should return a piece ofJSX, but a fewother return types (like strings) are supported. To calculate the returned JSX, therender method can readthis.props,this.state, andthis.context.
You should write therender method as a pure function, meaning that it should return the same result if props, state, and context are the same. It also shouldn’t contain side effects (like setting up subscriptions) or interact with the browser APIs. Side effects should happen either in event handlers or methods likecomponentDidMount.
Parameters
render does not take any parameters.
Returns
render can return any valid React node. This includes React elements such as<div />, strings, numbers,portals, empty nodes (null,undefined,true, andfalse), and arrays of React nodes.
Caveats
rendershould be written as a pure function of props, state, and context. It should not have side effects.renderwill not get called ifshouldComponentUpdateis defined and returnsfalse.WhenStrict Mode is on, React will call
rendertwice in development and then throw away one of the results. This helps you notice the accidental side effects that need to be moved out of therendermethod.There is no one-to-one correspondence between the
rendercall and the subsequentcomponentDidMountorcomponentDidUpdatecall. Some of therendercall results may be discarded by React when it’s beneficial.
setState(nextState, callback?)
CallsetState to update the state of your React component.
class FormextendsComponent{
state ={
name:'Taylor',
};
handleNameChange =(e)=>{
constnewName =e.target.value;
this.setState({
name:newName
});
}
render(){
return(
<>
<inputvalue={this.state.name}onChange={this.handleNameChange}/>
<p>Hello,{this.state.name}.</p>
</>
);
}
}setState enqueues changes to the component state. It tells React that this component and its children need to re-render with the new state. This is the main way you’ll update the user interface in response to interactions.
Pitfall
CallingsetStatedoes not change the current state in the already executing code:
functionhandleClick(){
console.log(this.state.name);// "Taylor"
this.setState({
name:'Robin'
});
console.log(this.state.name);// Still "Taylor"!
}It only affects whatthis.state will return starting from thenext render.
You can also pass a function tosetState. It lets you update state based on the previous state:
handleIncreaseAge =()=>{
this.setState(prevState=>{
return{
age:prevState.age +1
};
});
}You don’t have to do this, but it’s handy if you want to update state multiple times during the same event.
Parameters
nextState: Either an object or a function.- If you pass an object as
nextState, it will be shallowly merged intothis.state. - If you pass a function as
nextState, it will be treated as anupdater function. It must be pure, should take the pending state and props as arguments, and should return the object to be shallowly merged intothis.state. React will put your updater function in a queue and re-render your component. During the next render, React will calculate the next state by applying all of the queued updaters to the previous state.
- If you pass an object as
optional
callback: If specified, React will call thecallbackyou’ve provided after the update is committed.
Returns
setState does not return anything.
Caveats
Think of
setStateas arequest rather than an immediate command to update the component. When multiple components update their state in response to an event, React will batch their updates and re-render them together in a single pass at the end of the event. In the rare case that you need to force a particular state update to be applied synchronously, you may wrap it influshSync, but this may hurt performance.setStatedoes not updatethis.stateimmediately. This makes readingthis.stateright after callingsetStatea potential pitfall. Instead, usecomponentDidUpdateor the setStatecallbackargument, either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, you can pass a function tonextStateas described above.
Note
CallingsetState in class components is similar to calling aset function in function components.
shouldComponentUpdate(nextProps, nextState, nextContext)
If you defineshouldComponentUpdate, React will call it to determine whether a re-render can be skipped.
If you are confident you want to write it by hand, you may comparethis.props withnextProps andthis.state withnextState and returnfalse to tell React the update can be skipped.
class RectangleextendsComponent{
state ={
isHovered:false
};
shouldComponentUpdate(nextProps,nextState){
if(
nextProps.position.x ===this.props.position.x &&
nextProps.position.y ===this.props.position.y &&
nextProps.size.width ===this.props.size.width &&
nextProps.size.height ===this.props.size.height &&
nextState.isHovered ===this.state.isHovered
){
// Nothing has changed, so a re-render is unnecessary
returnfalse;
}
returntrue;
}
// ...
}React callsshouldComponentUpdate before rendering when new props or state are being received. Defaults totrue. This method is not called for the initial render or whenforceUpdate is used.
Parameters
nextProps: The next props that the component is about to render with. ComparenextPropstothis.propsto determine what changed.nextState: The next state that the component is about to render with. ComparenextStatetothis.stateto determine what changed.nextContext: The next context that the component is about to render with. ComparenextContexttothis.contextto determine what changed. Only available if you specifystatic contextType(modern) orstatic contextTypes(legacy).
Returns
Returntrue if you want the component to re-render. That’s the default behavior.
Returnfalse to tell React that re-rendering can be skipped.
Caveats
This methodonly exists as a performance optimization. If your component breaks without it, fix that first.
Consider using
PureComponentinstead of writingshouldComponentUpdateby hand.PureComponentshallowly compares props and state, and reduces the chance that you’ll skip a necessary update.We do not recommend doing deep equality checks or using
JSON.stringifyinshouldComponentUpdate. It makes performance unpredictable and dependent on the data structure of every prop and state. In the best case, you risk introducing multi-second stalls to your application, and in the worst case you risk crashing it.Returning
falsedoes not prevent child components from re-rendering whentheir state changes.Returning
falsedoes notguarantee that the component will not re-render. React will use the return value as a hint but it may still choose to re-render your component if it makes sense to do for other reasons.
Note
UNSAFE_componentWillMount()
If you defineUNSAFE_componentWillMount, React will call it immediately after theconstructor. It only exists for historical reasons and should not be used in any new code. Instead, use one of the alternatives:
- To initialize state, declare
stateas a class field or setthis.stateinside theconstructor. - If you need to run a side effect or set up a subscription, move that logic to
componentDidMountinstead.
See examples of migrating away from unsafe lifecycles.
Parameters
UNSAFE_componentWillMount does not take any parameters.
Returns
UNSAFE_componentWillMount should not return anything.
Caveats
UNSAFE_componentWillMountwill not get called if the component implementsstatic getDerivedStateFromPropsorgetSnapshotBeforeUpdate.Despite its naming,
UNSAFE_componentWillMountdoes not guarantee that the componentwill get mounted if your app uses modern React features likeSuspense. If a render attempt is suspended (for example, because the code for some child component has not loaded yet), React will throw the in-progress tree away and attempt to construct the component from scratch during the next attempt. This is why this method is “unsafe”. Code that relies on mounting (like adding a subscription) should go intocomponentDidMount.UNSAFE_componentWillMountis the only lifecycle method that runs duringserver rendering. For all practical purposes, it is identical toconstructor, so you should use theconstructorfor this type of logic instead.
Note
UNSAFE_componentWillReceiveProps(nextProps, nextContext)
If you defineUNSAFE_componentWillReceiveProps, React will call it when the component receives new props. It only exists for historical reasons and should not be used in any new code. Instead, use one of the alternatives:
- If you need torun a side effect (for example, fetch data, run an animation, or reinitialize a subscription) in response to prop changes, move that logic to
componentDidUpdateinstead. - If you need toavoid re-computing some data only when a prop changes, use amemoization helper instead.
- If you need to“reset” some state when a prop changes, consider either making a componentfully controlled orfully uncontrolled with a key instead.
- If you need to“adjust” some state when a prop changes, check whether you can compute all the necessary information from props alone during rendering. If you can’t, use
static getDerivedStateFromPropsinstead.
See examples of migrating away from unsafe lifecycles.
Parameters
nextProps: The next props that the component is about to receive from its parent component. ComparenextPropstothis.propsto determine what changed.nextContext: The next context that the component is about to receive from the closest provider. ComparenextContexttothis.contextto determine what changed. Only available if you specifystatic contextType(modern) orstatic contextTypes(legacy).
Returns
UNSAFE_componentWillReceiveProps should not return anything.
Caveats
UNSAFE_componentWillReceivePropswill not get called if the component implementsstatic getDerivedStateFromPropsorgetSnapshotBeforeUpdate.Despite its naming,
UNSAFE_componentWillReceivePropsdoes not guarantee that the componentwill receive those props if your app uses modern React features likeSuspense. If a render attempt is suspended (for example, because the code for some child component has not loaded yet), React will throw the in-progress tree away and attempt to construct the component from scratch during the next attempt. By the time of the next render attempt, the props might be different. This is why this method is “unsafe”. Code that should run only for committed updates (like resetting a subscription) should go intocomponentDidUpdate.UNSAFE_componentWillReceivePropsdoes not mean that the component has receiveddifferent props than the last time. You need to comparenextPropsandthis.propsyourself to check if something changed.React doesn’t call
UNSAFE_componentWillReceivePropswith initial props during mounting. It only calls this method if some of component’s props are going to be updated. For example, callingsetStatedoesn’t generally triggerUNSAFE_componentWillReceivePropsinside the same component.
Note
CallingsetState insideUNSAFE_componentWillReceiveProps in a class component to “adjust” state is equivalent tocalling theset function fromuseState during rendering in a function component.
UNSAFE_componentWillUpdate(nextProps, nextState)
If you defineUNSAFE_componentWillUpdate, React will call it before rendering with the new props or state. It only exists for historical reasons and should not be used in any new code. Instead, use one of the alternatives:
- If you need to run a side effect (for example, fetch data, run an animation, or reinitialize a subscription) in response to prop or state changes, move that logic to
componentDidUpdateinstead. - If you need to read some information from the DOM (for example, to save the current scroll position) so that you can use it in
componentDidUpdatelater, read it insidegetSnapshotBeforeUpdateinstead.
See examples of migrating away from unsafe lifecycles.
Parameters
nextProps: The next props that the component is about to render with. ComparenextPropstothis.propsto determine what changed.nextState: The next state that the component is about to render with. ComparenextStatetothis.stateto determine what changed.
Returns
UNSAFE_componentWillUpdate should not return anything.
Caveats
UNSAFE_componentWillUpdatewill not get called ifshouldComponentUpdateis defined and returnsfalse.UNSAFE_componentWillUpdatewill not get called if the component implementsstatic getDerivedStateFromPropsorgetSnapshotBeforeUpdate.It’s not supported to call
setState(or any method that leads tosetStatebeing called, like dispatching a Redux action) duringcomponentWillUpdate.Despite its naming,
UNSAFE_componentWillUpdatedoes not guarantee that the componentwill update if your app uses modern React features likeSuspense. If a render attempt is suspended (for example, because the code for some child component has not loaded yet), React will throw the in-progress tree away and attempt to construct the component from scratch during the next attempt. By the time of the next render attempt, the props and state might be different. This is why this method is “unsafe”. Code that should run only for committed updates (like resetting a subscription) should go intocomponentDidUpdate.UNSAFE_componentWillUpdatedoes not mean that the component has receiveddifferent props or state than the last time. You need to comparenextPropswiththis.propsandnextStatewiththis.stateyourself to check if something changed.React doesn’t call
UNSAFE_componentWillUpdatewith initial props and state during mounting.
Note
There is no direct equivalent toUNSAFE_componentWillUpdate in function components.
static childContextTypes
Deprecated
This API will be removed in a future major version of React.Usestatic contextType instead.
Lets you specify whichlegacy context is provided by this component.
static contextTypes
Deprecated
This API will be removed in a future major version of React.Usestatic contextType instead.
Lets you specify whichlegacy context is consumed by this component.
static contextType
If you want to readthis.context from your class component, you must specify which context it needs to read. The context you specify as thestatic contextType must be a value previously created bycreateContext.
class ButtonextendsComponent{
staticcontextType =ThemeContext;
render(){
consttheme =this.context;
constclassName ='button-' +theme;
return(
<buttonclassName={className}>
{this.props.children}
</button>
);
}
}Note
Readingthis.context in class components is equivalent touseContext in function components.
static defaultProps
You can definestatic defaultProps to set the default props for the class. They will be used forundefined and missing props, but not fornull props.
For example, here is how you define that thecolor prop should default to'blue':
class ButtonextendsComponent{
staticdefaultProps ={
color:'blue'
};
render(){
return<buttonclassName={this.props.color}>click me</button>;
}
}If thecolor prop is not provided or isundefined, it will be set by default to'blue':
<>
{/* this.props.color is "blue" */}
<Button/>
{/* this.props.color is "blue" */}
<Buttoncolor={undefined}/>
{/* this.props.color is null */}
<Buttoncolor={null}/>
{/* this.props.color is "red" */}
<Buttoncolor="red"/>
</>Note
DefiningdefaultProps in class components is similar to usingdefault values in function components.
static propTypes
You can definestatic propTypes together with theprop-types library to declare the types of the props accepted by your component. These types will be checked during rendering and in development only.
importPropTypesfrom'prop-types';
class GreetingextendsReact.Component{
staticpropTypes ={
name:PropTypes.string
};
render(){
return(
<h1>Hello,{this.props.name}</h1>
);
}
}Note
We recommend usingTypeScript instead of checking prop types at runtime.
static getDerivedStateFromError(error)
If you definestatic getDerivedStateFromError, React will call it when a child component (including distant children) throws an error during rendering. This lets you display an error message instead of clearing the UI.
Typically, it is used together withcomponentDidCatch which lets you send the error report to some analytics service. A component with these methods is called anerror boundary.
Parameters
error: The error that was thrown. In practice, it will usually be an instance ofErrorbut this is not guaranteed because JavaScript allows tothrowany value, including strings or evennull.
Returns
static getDerivedStateFromError should return the state telling the component to display the error message.
Caveats
static getDerivedStateFromErrorshould be a pure function. If you want to perform a side effect (for example, to call an analytics service), you need to also implementcomponentDidCatch.
Note
There is no direct equivalent forstatic getDerivedStateFromError in function components yet. If you’d like to avoid creating class components, write a singleErrorBoundary component like above and use it throughout your app. Alternatively, use thereact-error-boundary package which does that.
static getDerivedStateFromProps(props, state)
If you definestatic getDerivedStateFromProps, React will call it right before callingrender, both on the initial mount and on subsequent updates. It should return an object to update the state, ornull to update nothing.
This method exists forrare use cases where the state depends on changes in props over time. For example, thisForm component resets theemail state when theuserID prop changes:
class FormextendsComponent{
state ={
email:this.props.defaultEmail,
prevUserID:this.props.userID
};
staticgetDerivedStateFromProps(props,state){
// Any time the current user changes,
// Reset any parts of state that are tied to that user.
// In this simple example, that's just the email.
if(props.userID !==state.prevUserID){
return{
prevUserID:props.userID,
email:props.defaultEmail
};
}
returnnull;
}
// ...
}Note that this pattern requires you to keep a previous value of the prop (likeuserID) in state (likeprevUserID).
Pitfall
Deriving state leads to verbose code and makes your components difficult to think about.Make sure you’re familiar with simpler alternatives:
- If you need toperform a side effect (for example, data fetching or an animation) in response to a change in props, use
componentDidUpdatemethod instead. - If you want tore-compute some data only when a prop changes,use a memoization helper instead.
- If you want to“reset” some state when a prop changes, consider either making a componentfully controlled orfully uncontrolled with a key instead.
Parameters
props: The next props that the component is about to render with.state: The next state that the component is about to render with.
Returns
static getDerivedStateFromProps return an object to update the state, ornull to update nothing.
Caveats
This method is fired onevery render, regardless of the cause. This is different from
UNSAFE_componentWillReceiveProps, which only fires when the parent causes a re-render and not as a result of a localsetState.This method doesn’t have access to the component instance. If you’d like, you can reuse some code between
static getDerivedStateFromPropsand the other class methods by extracting pure functions of the component props and state outside the class definition.
Note
Implementingstatic getDerivedStateFromProps in a class component is equivalent tocalling theset function fromuseState during rendering in a function component.
Usage
Defining a class component
To define a React component as a class, extend the built-inComponent class and define arender method:
import{Component}from'react';
class GreetingextendsComponent{
render(){
return<h1>Hello,{this.props.name}!</h1>;
}
}React will call yourrender method whenever it needs to figure out what to display on the screen. Usually, you will return someJSX from it. Yourrender method should be apure function: it should only calculate the JSX.
Similarly tofunction components, a class component canreceive information by props from its parent component. However, the syntax for reading props is different. For example, if the parent component renders<Greeting name="Taylor" />, then you can read thename prop fromthis.props, likethis.props.name:
import{Component}from'react';class GreetingextendsComponent{render(){return<h1>Hello,{this.props.name}!</h1>;}}exportdefaultfunctionApp(){return(<><Greetingname="Sara"/><Greetingname="Cahal"/><Greetingname="Edite"/></>);}
Note that Hooks (functions starting withuse, likeuseState) are not supported inside class components.
Pitfall
We recommend defining components as functions instead of classes.See how to migrate.
Adding state to a class component
To addstate to a class, assign an object to a property calledstate. To update state, callthis.setState.
import{Component}from'react';exportdefaultclass CounterextendsComponent{state ={name:'Taylor',age:42,};handleNameChange =(e)=>{this.setState({name:e.target.value});}handleAgeChange =()=>{this.setState({age:this.state.age +1});};render(){return(<><inputvalue={this.state.name}onChange={this.handleNameChange}/><buttononClick={this.handleAgeChange}> Increment age</button><p>Hello,{this.state.name}. You are{this.state.age}.</p></>);}}
Pitfall
We recommend defining components as functions instead of classes.See how to migrate.
Adding lifecycle methods to a class component
There are a few special methods you can define on your class.
If you define thecomponentDidMount method, React will call it when your component is added(mounted) to the screen. React will callcomponentDidUpdate after your component re-renders due to changed props or state. React will callcomponentWillUnmount after your component has been removed(unmounted) from the screen.
If you implementcomponentDidMount, you usually need to implement all three lifecycles to avoid bugs. For example, ifcomponentDidMount reads some state or props, you also have to implementcomponentDidUpdate to handle their changes, andcomponentWillUnmount to clean up whatevercomponentDidMount was doing.
For example, thisChatRoom component keeps a chat connection synchronized with props and state:
import{Component}from'react';import{createConnection}from'./chat.js';exportdefaultclass ChatRoomextendsComponent{state ={serverUrl:'https://localhost:1234'};componentDidMount(){this.setupConnection();}componentDidUpdate(prevProps,prevState){if(this.props.roomId !==prevProps.roomId ||this.state.serverUrl !==prevState.serverUrl){this.destroyConnection();this.setupConnection();}}componentWillUnmount(){this.destroyConnection();}setupConnection(){this.connection =createConnection(this.state.serverUrl,this.props.roomId);this.connection.connect();}destroyConnection(){this.connection.disconnect();this.connection =null;}render(){return(<><label> Server URL:{' '}<inputvalue={this.state.serverUrl}onChange={e=>{this.setState({serverUrl:e.target.value});}}/></label><h1>Welcome to the{this.props.roomId} room!</h1></>);}}
Note that in development whenStrict Mode is on, React will callcomponentDidMount, immediately callcomponentWillUnmount, and then callcomponentDidMount again. This helps you notice if you forgot to implementcomponentWillUnmount or if its logic doesn’t fully “mirror” whatcomponentDidMount does.
Pitfall
We recommend defining components as functions instead of classes.See how to migrate.
Catching rendering errors with an error boundary
By default, if your application throws an error during rendering, React will remove its UI from the screen. To prevent this, you can wrap a part of your UI into anerror boundary. An error boundary is a special component that lets you display some fallback UI instead of the part that crashed—for example, an error message.
To implement an error boundary component, you need to providestatic getDerivedStateFromError which lets you update state in response to an error and display an error message to the user. You can also optionally implementcomponentDidCatch to add some extra logic, for example, to log the error to an analytics service.
class ErrorBoundaryextendsReact.Component{
constructor(props){
super(props);
this.state ={hasError:false};
}
staticgetDerivedStateFromError(error){
// Update state so the next render will show the fallback UI.
return{hasError:true};
}
componentDidCatch(error,info){
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logErrorToMyService(error,info.componentStack);
}
render(){
if(this.state.hasError){
// You can render any custom fallback UI
returnthis.props.fallback;
}
returnthis.props.children;
}
}Then you can wrap a part of your component tree with it:
<ErrorBoundaryfallback={<p>Something went wrong</p>}>
<Profile/>
</ErrorBoundary>IfProfile or its child component throws an error,ErrorBoundary will “catch” that error, display a fallback UI with the error message you’ve provided, and send a production error report to your error reporting service.
You don’t need to wrap every component into a separate error boundary. When you think about thegranularity of error boundaries, consider where it makes sense to display an error message. For example, in a messaging app, it makes sense to place an error boundary around the list of conversations. It also makes sense to place one around every individual message. However, it wouldn’t make sense to place a boundary around every avatar.
Note
There is currently no way to write an error boundary as a function component. However, you don’t have to write the error boundary class yourself. For example, you can usereact-error-boundary instead.
Alternatives
Migrating a simple component from a class to a function
Typically, you willdefine components as functions instead.
For example, suppose you’re converting thisGreeting class component to a function:
import{Component}from'react';class GreetingextendsComponent{render(){return<h1>Hello,{this.props.name}!</h1>;}}exportdefaultfunctionApp(){return(<><Greetingname="Sara"/><Greetingname="Cahal"/><Greetingname="Edite"/></>);}
Define a function calledGreeting. This is where you will move the body of yourrender function.
functionGreeting(){
// ... move the code from the render method here ...
}Instead ofthis.props.name, define thename propusing the destructuring syntax and read it directly:
functionGreeting({name}){
return<h1>Hello,{name}!</h1>;
}Here is a complete example:
functionGreeting({name}){return<h1>Hello,{name}!</h1>;}exportdefaultfunctionApp(){return(<><Greetingname="Sara"/><Greetingname="Cahal"/><Greetingname="Edite"/></>);}
Migrating a component with state from a class to a function
Suppose you’re converting thisCounter class component to a function:
import{Component}from'react';exportdefaultclass CounterextendsComponent{state ={name:'Taylor',age:42,};handleNameChange =(e)=>{this.setState({name:e.target.value});}handleAgeChange =(e)=>{this.setState({age:this.state.age +1});};render(){return(<><inputvalue={this.state.name}onChange={this.handleNameChange}/><buttononClick={this.handleAgeChange}> Increment age</button><p>Hello,{this.state.name}. You are{this.state.age}.</p></>);}}
Start by declaring a function with the necessarystate variables:
import{useState}from'react';
functionCounter(){
const[name,setName] =useState('Taylor');
const[age,setAge] =useState(42);
// ...Next, convert the event handlers:
functionCounter(){
const[name,setName] =useState('Taylor');
const[age,setAge] =useState(42);
functionhandleNameChange(e){
setName(e.target.value);
}
functionhandleAgeChange(){
setAge(age +1);
}
// ...Finally, replace all references starting withthis with the variables and functions you defined in your component. For example, replacethis.state.age withage, and replacethis.handleNameChange withhandleNameChange.
Here is a fully converted component:
import{useState}from'react';exportdefaultfunctionCounter(){const[name,setName] =useState('Taylor');const[age,setAge] =useState(42);functionhandleNameChange(e){setName(e.target.value);}functionhandleAgeChange(){setAge(age +1);}return(<><inputvalue={name}onChange={handleNameChange}/><buttononClick={handleAgeChange}> Increment age</button><p>Hello,{name}. You are{age}.</p></>)}
Migrating a component with lifecycle methods from a class to a function
Suppose you’re converting thisChatRoom class component with lifecycle methods to a function:
import{Component}from'react';import{createConnection}from'./chat.js';exportdefaultclass ChatRoomextendsComponent{state ={serverUrl:'https://localhost:1234'};componentDidMount(){this.setupConnection();}componentDidUpdate(prevProps,prevState){if(this.props.roomId !==prevProps.roomId ||this.state.serverUrl !==prevState.serverUrl){this.destroyConnection();this.setupConnection();}}componentWillUnmount(){this.destroyConnection();}setupConnection(){this.connection =createConnection(this.state.serverUrl,this.props.roomId);this.connection.connect();}destroyConnection(){this.connection.disconnect();this.connection =null;}render(){return(<><label> Server URL:{' '}<inputvalue={this.state.serverUrl}onChange={e=>{this.setState({serverUrl:e.target.value});}}/></label><h1>Welcome to the{this.props.roomId} room!</h1></>);}}
First, verify that yourcomponentWillUnmount does the opposite ofcomponentDidMount. In the above example, that’s true: it disconnects the connection thatcomponentDidMount sets up. If such logic is missing, add it first.
Next, verify that yourcomponentDidUpdate method handles changes to any props and state you’re using incomponentDidMount. In the above example,componentDidMount callssetupConnection which readsthis.state.serverUrl andthis.props.roomId. This is whycomponentDidUpdate checks whetherthis.state.serverUrl andthis.props.roomId have changed, and resets the connection if they did. If yourcomponentDidUpdate logic is missing or doesn’t handle changes to all relevant props and state, fix that first.
In the above example, the logic inside the lifecycle methods connects the component to a system outside of React (a chat server). To connect a component to an external system,describe this logic as a single Effect:
import{useState,useEffect}from'react';
functionChatRoom({roomId}){
const[serverUrl,setServerUrl] =useState('https://localhost:1234');
useEffect(()=>{
constconnection =createConnection(serverUrl,roomId);
connection.connect();
return()=>{
connection.disconnect();
};
},[serverUrl,roomId]);
// ...
}ThisuseEffect call is equivalent to the logic in the lifecycle methods above. If your lifecycle methods do multiple unrelated things,split them into multiple independent Effects. Here is a complete example you can play with:
import{useState,useEffect}from'react';import{createConnection}from'./chat.js';exportdefaultfunctionChatRoom({roomId}){const[serverUrl,setServerUrl] =useState('https://localhost:1234');useEffect(()=>{constconnection =createConnection(serverUrl,roomId);connection.connect();return()=>{connection.disconnect();};},[roomId,serverUrl]);return(<><label> Server URL:{' '}<inputvalue={serverUrl}onChange={e=>setServerUrl(e.target.value)}/></label><h1>Welcome to the{roomId} room!</h1></>);}
Note
If your component does not synchronize with any external systems,you might not need an Effect.
Migrating a component with context from a class to a function
In this example, thePanel andButton class components readcontext fromthis.context:
import{createContext,Component}from'react';constThemeContext =createContext(null);class PanelextendsComponent{staticcontextType =ThemeContext;render(){consttheme =this.context;constclassName ='panel-' +theme;return(<sectionclassName={className}><h1>{this.props.title}</h1>{this.props.children}</section>);}}class ButtonextendsComponent{staticcontextType =ThemeContext;render(){consttheme =this.context;constclassName ='button-' +theme;return(<buttonclassName={className}>{this.props.children}</button>);}}functionForm(){return(<Paneltitle="Welcome"><Button>Sign up</Button><Button>Log in</Button></Panel>);}exportdefaultfunctionMyApp(){return(<ThemeContext.Providervalue="dark"><Form/></ThemeContext.Provider>)}
When you convert them to function components, replacethis.context withuseContext calls:
import{createContext,useContext}from'react';constThemeContext =createContext(null);functionPanel({title,children}){consttheme =useContext(ThemeContext);constclassName ='panel-' +theme;return(<sectionclassName={className}><h1>{title}</h1>{children}</section>)}functionButton({children}){consttheme =useContext(ThemeContext);constclassName ='button-' +theme;return(<buttonclassName={className}>{children}</button>);}functionForm(){return(<Paneltitle="Welcome"><Button>Sign up</Button><Button>Log in</Button></Panel>);}exportdefaultfunctionMyApp(){return(<ThemeContext.Providervalue="dark"><Form/></ThemeContext.Provider>)}