class
state
component lifeCycle intro
render
constructor
### render
the only requerd methoid is The render() method.
The render() function should be pure, meaning that it does not modify component state, and it does not directly interact with the browser.
If you need to interact with the browser, perform your work in componentDidMount() or the other lifecycle methods instead. Keeping render() pure makes components easier to think about.
### constructor(prop)
- what
The constructor for a React component is called before it is mounted.
- used for
Initializing local state by assigning an object to this.state.
Binding event handler methods to an instance.
- not to do
You should not call setState() in the constructor().
Constructor is the only place where you should assign this.state directly. In all other methods, you need to use this.setState() instead.
Avoid introducing any side-effects or subscriptions in the constructor. For those use cases, use componentDidMount() instead.
Avoid copying props into state! This is a common mistake
Only use this pattern if you intentionally want to ignore prop updates.
### componentDidMount()
- what
invoked immediately after a component is mounted (inserted into the tree).
- used for
requests.
Calling the setState() here will update state and cause another rendering but it will happen before the browser updates the UI. This is to ensure that the user will not see any UI updates with the double rendering.
## componentDidUpdate()
- what
invoked as soon as the updating happens(update state or prop or invoke forceUpdate a method.
This method is not called for the initial render
- used for
updating the DOM in response to prop or state changes.
do network requests as long as you compare the current props to previous props.
You may call setState() must be wrapped in a condition
componentDidUpdate(prevProps) {
if (this.props.userName !== prevProps.userName) {
this.fetchData(this.props.userName);
}
}
## componentWillUnmount()
- what
before a component is being removed from the DOM:
- used for
Perform any necessary cleanup, such as invalidating timers, canceling network requests
- not to
You should not call setState() because the component will never be re-rendered.
-------------------------------------------
Note
componentDidUpdate() will not be invoked if shouldComponentUpdate() returns false.
--------------------------
Rarely Used Lifecycle Methods
# 1- shouldComponentUpdate(nextProps, nextState)
Anytime setState() is called, the component re-renders by default. The shouldComponentUpdate() method is used to let React know if a component is not affected by the state and prop changes.
Do not rely on it to “prevent” a rendering, as this can lead to bugs.
As shown in the example above, this lifecycle should always return a boolean value to the question, “Should I re-render my component?”
# 2- static getDerivedStateFromProps(props, state)
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.
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 to perform a side effect (for example, data fetching or an animation) in response to a change in props, use componentDidUpdate lifecycle instead.
If you want to re-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 component fully controlled or fully uncontrolled with a key instead.
This method doesn’t have access to the component instance. If you’d like, you can reuse some code between getDerivedStateFromProps() and the other class methods by extracting pure functions of the component props and state outside the class definition.
Note that this method is fired on every render, regardless of the cause. This is in contrast to UNSAFE_componentWillReceiveProps, which only fires when the parent causes a re-render and not as a result of a local setState.
static getDerivedStateFromProps()
This is one of the newer lifecycle methods introduced very recently by the React team.
This will be a safer alternative to the previous lifecycle method componentWillReceiveProps().
It is called just before calling the render() method.
This is a static function that does not have access to “this“. getDerivedStateFromProps() returns an object to update state in response to prop changes. It can return a null if there is no change to state.
This method also exists only for rare use cases where the state depends on changes in props in a component.
static getDerivedStateFromProps(props, state) {
if (props.currentRow !== state.lastRow) {
return {
isScrollingDown: props.currentRow > state.lastRow,
lastRow: props.currentRow,
};
}
// Return null to indicate no change to state.
return null;
}
Keep in mind that this lifecycle method is fired on every render.
An example use case where this method may come in handy would be a <Transition> component that compares its previous and next children to decide which ones to animate in and out.
static getDerivedStateFromProps(nextProps, prevState) - Useful for acting on changes in props to trigger changes in state (compare new and previous values if you want to handle changes). Instead of calling setState, you either return an object with new state or null if you do not want a change in state. If a parent component causes a component to re-render, this method will be called even if props have not changed.
static getDerivedStateFromProps(nextProps, prevState)
getDerivedStateFromProps is invoked after a component is instantiated as well as when it receives new props. It should return an object to update state, or null to indicate that the new props do not require any state updates. Notice that this is a static method and must be prefixed with the static keyword.
Calling this.setState() generally doesn’t trigger getDerivedStateFromProps().
static getDerivedStateFromProps
This method as described above is a more modern way to change state depending on changes to the component and should be used instead of componentWillReceiveProps.
static getDerivedStateFromProps(nextProps, prevState)
getDerivedStateFromProps is invoked after a component is instantiated as well as when it receives new props. It should return an object to update state, or null to indicate that the new props do not require any state updates. Notice that this is a static method and must be prefixed with the static keyword.
Calling this.setState() generally doesn’t trigger getDerivedStateFromProps().
static getDerivedStateFromProps
This method as described above is a more modern way to change state depending on changes to the component and should be used instead of componentWillReceiveProps.
# 3- getSnapshotBeforeUpdate(prevProps, prevState)
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().
For example:
class ScrollingList extends React.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) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
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) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}
In the above examples, it is important to read the scrollHeight property in getSnapshotBeforeUpdate because there may be delays between “render” phase lifecycles (like render) and “commit” phase lifecycles (like getSnapshotBeforeUpdate and componentDidUpdate).
It is called right before the DOM is updated. The value that is returned from getSnapshotBeforeUpdate() is passed on to componentDidUpdate().
Resizing the window during an async rendering is a good use-case of when the getSnapshotBeforeUpdate() can be utilized.
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps, prevState){
// perform any preparations for an upcoming update
}
# 4- forceUpdate()
component.forceUpdate(callback)
Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate(). This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate() method of each child. React will still only update the DOM if the markup changes.
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().
# 5- componentWillMount (UNSAFE_componentWillMount())
The first life cycle method we haven't seen before is componentWillMount, which is called before the render method is executed the first time. Since this method is called before render, this means that the component has not been added to the DOM yet and we cannot use React refs. It is important to note that setting the state in this phase will not trigger a re-rendering (since nothing has been rendered!).
componentWillMount(){
console.log('In componentWillMount');
// nothing has rendered yet
// Props have been initialized
console.log(this.props);
// State has been initialized
console.log(this.state);
}
The componentWillMount method is not used as frequently as the next method we will discuss, comonentDidMount. Sometimes you will see it used for initial configuration of the component, but this can also often be done directly in the constructor. In both life cycle methods you have access to props and state, but not much else. This method will be deprecated in React 17 and methods like componentDidMount or getDerivedStateFromProps should be used instead. It will be renamed to UNSAFE_componentWillMount()
# 6- componentWillReceiveProps (UNSAFE_componentWillReceiveProps)
This life cycle method is only called when the props have changed and when this is not an initial rendering. componentWillReceiveProps allows us to update the state depending on the existing and upcoming props before the render method has been called. This is essential when you want to intercept the passing down of props from a parent component to a child component. For example, maybe you want to set some state only when a particular prop is about to change, but not otherwise. This method will be deprecated in React 17 and will be renamed to UNSAFE_componentWillReceiveProps()
componentWillReceiveProps(nextProps) {
if (this.props.someProp !== nextProps.someProp) {
this.setState({
// set some state
});
}
}
componentWillReceiveProps (UNSAFE_componentWillReceiveProps)
This life cycle method is only called when the props have changed and when this is not an initial rendering. componentWillReceiveProps allows us to update the state depending on the existing and upcoming props before the render method has been called. This is essential when you want to intercept the passing down of props from a parent component to a child component. For example, maybe you want to set some state only when a particular prop is about to change, but not otherwise.
componentWillReceiveProps(nextProps) {
if (this.props.someProp !== nextProps.someProp) {
this.setState({
// set some state
});
}
}
use componentDidUpdate lifecycle instead.
If you used componentWillReceiveProps for re-computing some data only when a prop changes, use a memoization helper instead.
If you used componentWillReceiveProps to “reset” some state when a prop changes, consider either making a component fully controlled or fully uncontrolled with a key instead.
For other use cases, follow the recommendations in this blog post about derived state.
UNSAFE_componentWillReceiveProps() is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may compare this.props and nextProps and perform state transitions using this.setState() in this method.
Note that if a parent component causes your component to re-render, this method will be called even if props have not changed. Make sure to compare the current and next values if you only want to handle changes.
React doesn’t call UNSAFE_componentWillReceiveProps() with initial props during mounting. It only calls this method if some of component’s props may update. Calling this.setState() generally doesn’t trigger UNSAFE_componentWillReceiveProps().
# 7- componentWillUpdate (UNSAFE_componentWillUpdate)
componentWillUpdate gets called as soon as the the shouldComponentUpdate returns true. This is sort of analogous to the componentWillMount hook; the difference now is that we're updating an existing component, not mounting a new one. You cannot call setState here. If you need to update state in response to a change in props, use getDerivedStateFromPRops instead. This method will be deprecated in React 17 and methods like getDerivedStateFromProps should be used instead. It will be renamed to UNSAFE_componentWillUpdate()
componentWillUpdate(nextProps, nextState){
// perform any preparations for an upcoming update
}
render
We've seen this one before! Just always remember - changing state triggers a re-render unless you modify shouldComponentUpdate.
componentWillUpdate (UNSAFE_componentWillUpdate)
componentWillUpdate gets called as soon as the the shouldComponentUpdate returns true. This is sort of analogous to the componentWillMount hook; the difference now is that we're updating an existing component, not mounting a new one. You cannot call setState here. If you need to update state in response to a change in props, use getDerivedStateFromPRops instead. This method will be deprecated in React 17 and methods like getDerivedStateFromProps should be used instead. It will be renamed to UNSAFE_componentWillUpdate()
componentWillUpdate(nextProps, nextState){
// perform any preparations for an upcoming update
}
render
We've seen this one before! Just always remember - changing state triggers a re-render unless you modify shouldComponentUpdate.
To recap what happens when setState runs:
componentWillReceiveProps runs
getDerivedStateFromProps runs
shouldComponentUpdate runs - if it returns false, render does not run
componentWillUpdate runs
render runs
getSnapshotBeforeUpdate runs
componentDidUpdate runs
Removing a component (unmounting)
To recap what happens when setState runs:
componentWillReceiveProps runs
getDerivedStateFromProps runs
shouldComponentUpdate runs - if it returns false, render does not run
componentWillUpdate runs
render runs
getSnapshotBeforeUpdate runs
componentDidUpdate runs
Removing a component (unmounting)
componentWillUnmount
-----------------------------------------
# Error
componentDidCatch
In React 16, Error Boundaries, a more friendly way to catch errors were introduced. A class component can become an error boundary if it defines a lifecycle method called componentDidCatch. So what's the idea here?
Error boundaries are components that can catch errors anywhere in component (including any children component they render), and log errors and/or display a fallback UI. The componentDidCatch lifecycle hook is meant to catch errors during mounting, rendering and in other lifecycle methods.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// Display fallback UI
this.setState({ hasError: true });
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
// render anything inside of this component
return this.props.children;
}
}
It could then be used like this:
<ErrorBoundary>
<SomeComponent />
</ErrorBoundary>
In short, error boundaries are almost identical to try/catch blocks (but instead of the imperative try/catch, we use a far more declarative syntax), but for your entire component and any children they render.
Only use error boundaries for recovering from unexpected exceptions; don’t try to use them for control flow.
Error boundaries
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.
A class component becomes an error boundary if it defines either (or both) of the lifecycle methods static getDerivedStateFromError() or componentDidCatch(). Updating state from these lifecycles lets you capture an unhandled JavaScript error in the below tree and display a fallback UI.
Only use error boundaries for recovering from unexpected exceptions; don’t try to use them for control flow.
For more details, see Error Handling in React 16.
Note
Error boundaries only catch errors in the components below them in the tree. An error boundary can’t catch an error within itself.
static getDerivedStateFromError()
static getDerivedStateFromError(error)
This lifecycle is invoked after an error has been thrown by a descendant component. It receives the error that was thrown as a parameter and should return a value to update state.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
Note
getDerivedStateFromError() is called during the “render” phase, so side-effects are not permitted. For those use cases, use componentDidCatch() instead.
componentDidCatch()
componentDidCatch(error, info)
This lifecycle is invoked after an error has been thrown by a descendant component. It receives two parameters:
error - The error that was thrown.
info - An object with a componentStack key containing information about which component threw the error.
componentDidCatch() is called during the “commit” phase, so side-effects are permitted. It should be used for things like logging errors:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(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
logComponentStackToMyService(info.componentStack);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
Production and development builds of React slightly differ in the way componentDidCatch() handles errors.
On development, the errors will bubble up to window, this means that any window.onerror or window.addEventListener('error', callback) will intercept the errors that have been caught by componentDidCatch().
On production, instead, the errors will not bubble up, which means any ancestor error handler will only receive errors not explicitly caught by componentDidCatch().
Note
In the event of an error, you can render a fallback UI with componentDidCatch() by calling setState, but this will be deprecated in a future release. Use static getDerivedStateFromError() to handle fallback rendering instead.
componentDidCatch
In React 16, Error Boundaries, a more friendly way to catch errors were introduced. A class component can become an error boundary if it defines a lifecycle method called componentDidCatch. So what's the idea here?
Error boundaries are components that can catch errors anywhere in component (including any children component they render), and log errors and/or display a fallback UI. The componentDidCatch lifecycle hook is meant to catch errors during mounting, rendering and in other lifecycle methods.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// Display fallback UI
this.setState({ hasError: true });
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
// render anything inside of this component
return this.props.children;
}
}
It could then be used like this:
<ErrorBoundary>
<SomeComponent />
</ErrorBoundary>
In short, error boundaries are almost identical to try/catch blocks (but instead of the imperative try/catch, we use a far more declarative syntax), but for your entire component and any children they render.
Only use error boundaries for recovering from unexpected exceptions; don’t try to use them for control flow.
static getDerivedStateFromProps(nextProps, prevState) - Useful for acting on changes in props to trigger changes in state (compare new and previous values if you want to handle changes). Instead of calling setState, you either return an object with new state or null if you do not want a change in state. If a parent component causes a component to re-render, this method will be called even if props have not changed.