Как заставить react обновить компонент
Перейти к содержимому

Как заставить react обновить компонент

  • автор:

React: полное руководство по повторному рендерингу

Представляю вашему вниманию перевод этой замечательной статьи, посвященной повторному рендерингу (re-render, далее — ререндеринг) в React.

Что такое ререндеринг?

Существует 2 основные стадии, которым следует уделять пристальное внимание, когда речь заходит о производительности в React :

  • первоначальный рендеринг (initial rendering) — происходит, когда компонент впервые появляется на экране;
  • ререндеринг — второй и последующие рендеринги компонента.

Ререндеринг происходит, когда React необходимо обновить приложение некоторыми данными. Обычно, это является результатом действий пользователя, получения ответа на асинхронный запрос или публикацию при подписке (паттерн «pub/sub» — публикация/подписка или издатель/подписчик) на определенные данные.

Что такое необходимый и лишний (ненужный) ререндеринги?

Необходимый (necessary) ререндеринг — это повторный рендеринг компонента, подвергшегося некоторым изменениям или получившего новые данные. Например, если пользователь вводит данные в поле (инпут), компонент, управляющий состоянием, должен обновляться при вводе каждого символа, т. е. ререндериться.

Лишний (unnecessary) ререндеринг — повторный рендеринг компонента, вызываемый различными механизмами ререндеринга в результате ошибки или неэффективной архитектуры приложения. Например, если при вводе данных в инпут пользователем ререндерится вся страница, такой ререндеринг, скорее всего, является лишним.

Сам по себе лишний рендеринг не является проблемой: React является достаточно быстрым, чтобы выполнять его незаметно для пользователя.

Однако, если ререндеринг происходит очень часто или речь идет о тяжелом с точки зрения производительности компоненте, пользовательский опыт может быть испорчен «лаганием» (временной утратой интерактивности страницей), заметными задержками в ответ на взаимодействие пользователя со страницей или полным зависанием страницы.

Когда происходит ререндеринг?

Существует 4 причины, по которым компонент подвергается ререндерингу: изменение состояния, ререндеринг родительского компонента, изменение контекста и изменение хука. Существует распространенный миф о том, что ререндеринг происходит также при изменении пропов. Это не совсем так (см. ниже).

Модификация состояния

Компонент всегда подвергается ререндерингу при изменении его состояния. Обычно, это происходит в функции обратного вызова или в хуке useEffect .

Изменения состояния влекут за собой безусловный (непредотвращаемый) ререндеринг

Ререндеринг предка

Компонент подвергается ререндерингу при повторном рендеринге его родительского компонента. Другими словами, когда компонент повторно рендерится, его потомки также ререндерятся.

Ререндеринг «спускается» вниз по дереву компонентов: повторный рендеринг дочернего компонента не влечет ререндеринг его предка (на самом деле, существует несколько пограничных случаев, когда такое возможно: The mystery of React Element, children, parents and re-renders).

Модификация контекста

При изменении значения, передаваемого в провайдер контекста (Context Provider), все компоненты, потребляющие (consume) контекст (эти значения), подвергаются повторному рендерингу, даже если они не используют модифицированные данные. Данный вид ререндеринга нелегко предотвратить, но это возможно (см. ниже).

Модификация хука

Все, что происходит внутри хука, «принадлежит» использующему его компоненту. Здесь действуют те же правила:

  • изменение состояния хука влечет безусловный ререндеринг «хостового» (host) компонента;
  • если хук потребляет контекст, модификация контекста повлечет безусловный ререндеринг компонента, использующего хук.

Хуки могут вызываться по цепочке. Каждый хук в цепочке принадлежит хостовому компоненту — модификация любого хука влечет безусловный ререндеринг соответствующего компонента.

Изменение пропов (распространенное заблуждение)

До тех пор, пока речь не идет о мемоизированных компонентах, изменения пропов особого значения не имеют.

Модификация пропов означает их обновление родительским компонентом. Это, в свою очередь, означает ререндеринг родительского компонента, влекущий повторный рендеринг всех его потомков.

Изменения пропов становятся важными только при применении различных техник мемоизации ( React.memo , useMemo ).

Предотвращение ререндеринга с помощью композиции

Антипаттерн: создание компонентов в функции рендеринга

Создание компонентов внутри функции рендеринга другого компонента является антипаттерном, который может очень негативно влиять на производительность. React будет повторно монтировать (remount), т. е. уничтожать и создавать с нуля такой компонент при каждом рендеринге, что будет существенно замедлять обычный рендеринг. Это может привести к таким багам, как:

  • «вспышки» (flashes) разного контента в процессе рендеринга;
  • сброс состояния компонента при каждом рендеринге;
  • запуск useEffect без зависимостей при каждом рендеринге;
  • потеря фокуса, если компонент находился в этом состоянии и т. д.

Паттерн: перемещение состояния вниз

Данный паттерн используется, когда тяжелый компонент управляет состоянием, которое используется лишь небольшой частью дерева компонентов. Типичным примером может быть открытие/закрытие диалогового/модального окна при нажатии кнопки в сложном компоненте, который рендерит существенную часть страницы.

В этом случае состояние, управляющее видимостью окна, само окно и кнопка, вызывающая обновление состояния окна, могут быть инкапсулированы в отдельном компоненте. Как результат, большой компонент не будет ререндериться при модификации такого состояния.

Паттерн: передача потомков в виде пропов

Это называется «оборачиванием состояния вокруг потомков». Данная техника похожа на предыдущую: изменения состояния инкапсулируются в меньшем компоненте. Разница состоит в том, что состояние используется в качестве обертки медленной часть дерева рендеринга, что облегчает его извлечение. Типичными примерами являются обработчики onScroll или omMouseMove , зарегистрированные на корневом элементе компонента.

В этом случае управление состоянием и использующий его компонент могут быть извлечены в отдельный компонент, а медленный компонент может передаваться ему как children . С точки зрения инкапсулирующего компонента children — обычный проп, поэтому потомки не подвергаются ререндерингу при модификации состояния.

Паттерн: передача компонентов в виде пропов

Данный паттерн очень похож на предыдущий: состояние инкапсулируется внутри меньшего компонента, а большом компонент передается ему как props . Пропы не затрагиваются модификацией состояния, поэтому тяжелый компонент не подвергается ререндерингу.

Может использоваться в случае, когда несколько больших компонентов не зависят от состояния, но не могут быть извлечены как children .

Предотвращение ререндеринга с помощью React.memo

Оборачивание компонента в React.memo останавливает нисходящую цепочку ререндерингов, запущенную где-то выше в дереве компонентов, до тех пор, пока пропы остаются неизменными.

Может использоваться в тяжелых компонентах, не зависящих от источника ререндеринга (состояние, данные и др.).

React.memo : компонент с пропами

Все пропы, которые не являются примитивными значениями, должны мемоизироваться, например, с помощью хука useMemo до передачи компоненту, мемоизируемому с помощью React.memo .

React.memo : компоненты, передаваемыми в виде пропов, или потомки

Компоненты, передаваемые другим компонентам как пропы, или дочерние компоненты должны мемоизироваться с помощью React.memo . Мемоизация родительского компонента работать не будет: потомки и компоненты-пропы — это объекты, которые будут разными при каждом рендеринге.

Повышение производительности ререндеринга с помощью хуков useCallback и useMemo

Антипаттерн: ненужная мемоизация пропов с помощью useCallback/useMemo

Мемоизация пропов сама по себе не предотвращает ререндеринг дочернего компонента. Повторный рендеринг родительского компонента влечет безусловный ререндеринг его потомков независимо от пропов.

Обязательное применение useMemo/useCallback

Если дочерний компонент обернут в React.memo , все пропы, не являющиеся примитивами, должны быть предварительно мемоизированы.

Если компонент использует непримитивные значения в качестве зависимостей таких хуков, как useEffect , useMemo или useCallback , они также должны быть мемоизированы.

Использование useMemo для «дорогих» вычислений

Хук useMemo предназначен для предотвращения дорогих с точки зрения производительности вычислений при повторных рендерингах.

Использование useMemo имеет свою цену: потребляется больше памяти и, как следствие, первоначальный рендеринг становится медленнее. Поэтому его следует применять с умом. В React самые дорогие вычисления производятся при монтировании и обновлении компонентов.

Поэтому типичным примером использования useMemo является мемоизация React-элементов . Такими элементами, как правило, является часть существующего дерева рендеринга или результат генерации такого дерева, например, функция map , возвращающая массив элементов.

Стоимость «чистых» операций, таких как сортировка или фильтрация массива, обычно, являются незначительными по сравнению с обновлениями компонентов.

Повышение производительности ререндеринга списков

Когда речь идет о ререндеринге списков, проп key может иметь важное значение.

Внимание: само по себе предоставление пропа key не повышает производительность рендеринга списка. Для предотвращения ререндеринга элементов списка, они должны оборачиваться в React.memo и следовать другим лучшим практикам.

Значением пропа key должна быть строка, уникальная в пределах компонента и стабильная для элемента. Как правила, для этого используется id или индекс элемента в массиве.

Внимание: индекс следует использовать только в крайнем случае, когда можно быть уверенным, что список является статичным — количество и порядок элементов являются постоянными величинами. Если элементы добавляются/удаляются/вставляются/меняются местами, индексы использовать нельзя.

Использование индексов в качестве ключей элементов динамического списка может привести к:

  • багам, связанным с неправильным состоянием компонентов или неуправляемых элементов (таких как поля для ввода);
  • снижению производительности, если компоненты обернуты в React.memo .

Антипаттерн: произвольные значения пропа key

Значением key никогда не должны быть рандомные значения. Это приведет к перемонтированию элементов списка при каждом рендеринге, что повлечет за собой:

  • очень низкую производительность списка;
  • баги, связанные с неправильным состоянием компонентов или неуправляемых элементов (таких как поля для ввода).

Предотвращение ререндеринга, вызываемого контекстом

Мемоизация значения, передаваемого провайдеру

Если провайдер контекста находится не на верхнем уровне приложения и существует вероятность того, что он подвергнется ререндерингу вследствие повторного рендеринга его предков, значение, передаваемое провайдеру, должно быть мемоизировано.

Разделение данных и интерфейсов

Если контекст содержит комбинацию данных и интерфейсов (геттеров и сеттеров), они могут быть разделены на разные провайдеры в рамках одного компонента. Это предотвратит ререндеринг компонентов, которые, например, используют API , но не зависят от данных.

Разделение данных на части

Если контекст управляет несколькими независимыми частями данных (data chunks), его можно разделить на несколько провайдеров. В результате ререндериться буду только компоненты, потребляющие модифицированные данные.

Селекторы контекста

Компонент подвергается безусловному ререндерингу при любом изменении контекста, даже если потребляемое им значение осталось прежним, даже с помощью useMemo .

Однако, можно сымитировать селекторы контекста с помощью компонентов высшего порядка (higher-order components, HOC) и React.memo .

Надеюсь, что вы, как и я, нашли для себя что-то интересное и не зря потратили время. Благодарю за внимание и happy coding!

How and when to force a React component to re-render

React Logo

React usually automatically re-renders components, but for us to truly understand how and when to force React to re-render a component, we need to understand the inner workings of React.

Since the beginning of the web, we’ve used HTML and CSS to define the visual representation of a website. This has not changed, but, with the introduction of JavaScript, new concepts that enable us to read and update the rendered HTML of a page. We call this API DOM.

Libraries like jQuery became extremely popular because they provide an abstraction layer on top of the DOM API that provides enhanced functionality and compatibility, making it easy for developers to build web applications.

But jQuery has its limitations. It doesn’t solve crucial problems developers have when working with dynamically loaded content, such as keeping the JavaScript state (variables) and the DOM (HTML) in sync. Changing a variable in JavaScript does not affect the DOM directly.

Using a framework like React can solve this problem. React relies on JavaScript to maintain the state of an application. This master state object that contains a JavaScript reference to each object on the page is called Virtual DOM. Any changes on virtual DOM reflect automatically on the DOM, and that’s React’s best magic trick.

But how do we update the virtual DOM? We do this by building components and working with state and props.

The next question you may have is, what happens on the edge cases when a component is not updating as expected? Is it even possible? Maybe, but it’s complicated, so let’s discuss it.

Why aren’t React components re-rendering?

Generally, forcing a React component re-render isn’t best practice, even when React fails to update the components automatically. So, before considering forcing a re-render, we should analyze our code, as React magic depends on us being good hosts.

Incorrectly updated state in React

Let’s build a simple component to demonstrate one common reason components aren’t rendering. We will build a simple app that will show a username, Juan , and, after pressing a button, the name will change to Peter .

Here is a demonstration of the app with the complete code. You probably noticed that after clicking the button, nothing happens, even though we changed our state on the button:

The component did not change, so there was no re-rendering trigger. Here’s why.

React evaluates state changes by checking its shallow equality (or reference equality), which checks to see if both the preview and new value for state reference the same object. In our example, we updated one of the properties of the user object, but we technically made setUser the same object reference, and thus, React didn’t perceive any change in its state.

State, as described in the React documentation, should be treated as immutable.

So, how do we fix it? We could create a new object with the correct values as follows:

Note that we are using the spread operator in JavaScript to preserve the properties of the original object while updating its name property under a new object. The final result can be observed here.

Incorrectly updated props without state change

While it may seem impossible, incorrectly updating props without a state change can happen, and it usually leads to bugs. Let’s look at an example.

In this demo, I built a clock that has a major problem: the time doesn’t change after I first load the screen. Not a very useful clock, right?

Let’s take a look at the code responsible for calculating the current time:

This code looks ugly and is generally not a great way to code for a React component, but it works. Every second, the runtime will call the function setMyTime and will update the variable myTime , which is then passed to our Clock component for rendering.

This demo doesn’t work because props are a reflection of state, so a standalone change in props won’t trigger a re-render. To fix it, we need a total rewrite.

Notice that we introduced state to manage myTime and useEffect to start and clear the timers to avoid bugs when the component re-renders. And it works!

Forcing a React component to re-render

It’s typically frowned upon to force a component to re-render, and the failure of automatic re-rendering in React is often due to an underlying bug in our codebase. But, if you have a legitimate need to force a React component to re-render, there are a few ways to do it.

Over 200k developers use LogRocket to create better digital experiences

Learn more →

Forcing an update on a React class component

If you are using class components in your code, you’re in luck. React provides an official API to force a re-render, and it’s straightforward to implement:

In any user or system event, you can call the method this.forceUpdate() , which will cause render() to be called on the component, skipping shouldComponentUpdate() , and thus, forcing React to re-evaluate the Virtual DOM and DOM state.

There are some caveats to this method:

  • React will trigger the normal lifecycle methods for child components, including shouldComponentUpdate() , so we only can force the current component to be re-rendered
  • VirtualDOM will still validate its state with DOM, so React will only update the DOM if the markup changes

Forcing an update on a function component

There’s no official API to re-render a function component, nor is there a React Hook. There are, however, some clever tricks to signal to React that a component should be updated.

  1. Replace state objects with a new instance of themselves

Let’s say we want to force a refresh on our change user example above. We could do something like this:

Because user is an object, we could copy it to a new object and set it as the new state. The same could apply to any other object or array.

2. Have an empty state variable trigger updates

This method is interesting, as it creates a new object in the state. We only care about its update function as follows:

Here, we use useCallback to memoize our forceUpdate function, thus keeping it constant throughout the component lifecycle and making it safe to be passed to child components as props .

Here is an example of how to use it:

Now, each time we click on the Force Re-render button, the component will re-render. You can access the live demo here.

Conclusion

In general, we should prevent forcing React to re-render components. If React fails to do re-render components automatically, it’s likely that an underlying issue in your project is preventing the components from updating correctly.

However, we covered a few common ways to force React to re-render components should it be required. Happy coding!

LogRocket: Full visibility into your production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket. LogRocket Dashboard Free Trial Banner

LogRocket combines session replay, product analytics, and error tracking – empowering software teams to create the ideal web and mobile product experience. What does that mean for you?

Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay problems as if they happened in your own browser to quickly understand what went wrong.

No more noisy alerting. Smart error tracking lets you triage and categorize issues, then learns from this. Get notified of impactful user issues, not false positives. Less alerts, way more useful signal.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

4 methods to force a re-render in React

Are you looking to for a way to force a re-render on a React Component?

Please enable JavaScript

Here are a few methods to re-render a React component.

First, if you’re looking to become a strong and elite React developer within just 11 modules, you might want to look into Wes Bos, Advanced React course for just $97.00 (30% off). Wouldn’t it be nice to learn how to create end-to-end applications in React to get a higher paying job? Wes Bos, Advanced React course will make you an elite React developer and will teach you the skillset for you to have the confidence to apply for React positions.

Click here to become a strong and elite React developer: Advanced React course.

Disclaimer: The three React course links are affiliate links where I may receive a small commission for at no cost to you if you choose to purchase a plan from a link on this page. However, these are merely the course I fully recommend when it comes to becoming a React expert.

1. Re-render component when state changes

Any time a React component state has changed, React has to run the render() method.

In the example above I’m update the state when the component mounts.

You can also re-render a component on an event, such as a click event.

Both outputs will look like this:

2. Re-render component when props change

In the example above, <Child /> component does not have state, but it does have a custom prop that it accepts, message .

When the button gets clicked on it will update the <Child /> component, and cause it to run the render() lifecycle again.

3. Re-render with key prop

I showed an example how to cause a re-render and run the componentDidMount() lifecycle, here.

By changing the value of the key prop, it will make React unmount the component and re-mount it again, and go through the render() lifecycle.

4. Force a re-render

This is a method that is highly discouraged. Always use props & state changes to cause a new render.

But nonetheless, here is how you can do it!

Conclusion

If you need to re-render a React component, always update the components state and props.

Try to avoid causing re-render with key prop, because it will add a bit more complexity. But There are odd use cases where this is needed.

Never use forceUpdate() to cause a re-render.

First, if you’re looking to become a strong and elite React developer within just 11 modules, you might want to look into Wes Bos, Advanced React course for just $97.00 (30% off). Wouldn’t it be nice to learn how to create end-to-end applications in React to get a higher paying job? Wes Bos, Advanced React course will make you an elite React developer and will teach you the skillset for you to have the confidence to apply for React positions.

Click here to become a strong and elite React developer: Advanced React course.

Disclaimer: The three React course links are affiliate links where I may receive a small commission for at no cost to you if you choose to purchase a plan from a link on this page. However, these are merely the course I fully recommend when it comes to becoming a React expert.

I like to tweet about React and post helpful code snippets. Follow me there if you would like some too!

Ruben Leija

I launched this blog in 2019 and now I write to 85,000 monthly readers about JavaScript. Say hi to me at Twitter, @rleija_.

Do you want more React articles?

Hey, here at Linguine Code, we want to teach you everything we know about React . Our only question is, are you in?

React.Component

Try the new React documentation for Component .

The new docs will soon replace this site, which will be archived. Provide feedback.

This page contains a detailed API reference for the React component class definition. It assumes you’re familiar with fundamental React concepts, such as Components and Props, as well as State and Lifecycle. If you’re not, read them first.

React lets you define components as classes or functions. Components defined as classes currently provide more features which are described in detail on this page. To define a React component class, you need to extend React.Component :

The only method you must define in a React.Component subclass is called render() . All the other methods described on this page are optional.

We strongly recommend against creating your own base component classes. In React components, code reuse is primarily achieved through composition rather than inheritance.

Note:

React doesn’t force you to use the ES6 class syntax. If you prefer to avoid it, you may use the create-react-class module or a similar custom abstraction instead. Take a look at Using React without ES6 to learn more.

The Component Lifecycle

Each component has several “lifecycle methods” that you can override to run code at particular times in the process. You can use this lifecycle diagram as a cheat sheet. In the list below, commonly used lifecycle methods are marked as bold. The rest of them exist for relatively rare use cases.

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

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:

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

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

Each component also provides some other APIs:

Commonly Used Lifecycle Methods

The methods in this section cover the vast majority of use cases you’ll encounter creating React components. For a visual reference, check out this lifecycle diagram.

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

When called, it should examine this.props and this.state and return one of the following types:

  • React elements. Typically created via JSX. For example, <div /> and <MyComponent /> are React elements that instruct React to render a DOM node, or another user-defined component, respectively.
  • Arrays and fragments. Let you return multiple elements from render. See the documentation on fragments for more details.
  • Portals. Let you render children into a different DOM subtree. See the documentation on portals for more details.
  • String and numbers. These are rendered as text nodes in the DOM.
  • Booleans or null or undefined . Render nothing. (Mostly exists to support return test && <Child /> pattern, where test is boolean).

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.

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.

If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor for your React component.

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.

Typically, in React constructors are only used for two purposes:

  • Initializing local state by assigning an object to this.state .
  • Binding event handler methods to an instance.

You should not call setState() in the constructor() . Instead, if your component needs to use local state, assign the initial state to this.state directly 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.

Note

Avoid copying props into state! This is a common mistake:

The problem is that it’s both unnecessary (you can use this.props.color directly instead), and creates bugs (updates to the color prop won’t be reflected in the state).

Only use this pattern if you intentionally want to ignore prop updates. In that case, it makes sense to rename the prop to be called initialColor or defaultColor . You can then force a component to “reset” its internal state by changing its key when necessary.

Read our blog post on avoiding derived state to learn about what to do if you think you need some state to depend on the props.

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.

This method is a good place to set up any subscriptions. If you do that, don’t forget to unsubscribe in componentWillUnmount() .

You may call setState() immediately in componentDidMount() . It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will 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 the constructor() instead. 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.

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).

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you’ll cause an infinite loop. It would also cause an extra re-rendering which, while not visible to the user, can affect the component performance. If you’re trying to “mirror” some state to a prop coming from above, consider using the prop directly instead. Read more about why copying props into state causes bugs.

If your component implements the getSnapshotBeforeUpdate() lifecycle (which is rare), the value it returns will be passed as a third “snapshot” parameter to componentDidUpdate() . Otherwise this parameter will be undefined.

Note

componentDidUpdate() will not be invoked if shouldComponentUpdate() returns false.

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.

Rarely Used Lifecycle Methods

The methods in this section correspond to uncommon use cases. They’re handy once in a while, but most of your components probably don’t need any of them. You can see most of the methods below on this lifecycle diagram if you click the “Show less common lifecycles” checkbox at the top of it.

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.

This method only exists as a performance optimization. Do not rely on it to “prevent” a rendering, as this can lead to bugs. Consider using the built-in PureComponent instead of writing shouldComponentUpdate() by hand. PureComponent performs a shallow comparison of props and state, and reduces the chance that you’ll skip a necessary update.

If you are confident you want to write it by hand, you may compare this.props with nextProps and this.state with nextState and return false to tell React the update can be skipped. Note that returning false does not prevent child components from re-rendering when their state changes.

We do not recommend doing deep equality checks or using JSON.stringify() in shouldComponentUpdate() . It is very inefficient and will harm performance.

Currently, if shouldComponentUpdate() returns false , then UNSAFE_componentWillUpdate() , render() , and componentDidUpdate() will not be invoked. In the future React may treat shouldComponentUpdate() as a hint rather than a strict directive, and returning false may still result in a re-rendering of the component.

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 .

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.

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 ).

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.

Note

Error boundaries only catch errors in the components below them in the tree. An error boundary can’t catch an error within itself.

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.

Note

getDerivedStateFromError() is called during the “render” phase, so side-effects are not permitted. For those use cases, use componentDidCatch() instead.

This lifecycle is invoked after an error has been thrown by a descendant component. It receives two parameters:

  1. error — The error that was thrown.
  2. 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:

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.

Legacy Lifecycle Methods

The lifecycle methods below are marked as “legacy”. They still work, but we don’t recommend using them in the new code. You can learn more about migrating away from legacy lifecycle methods in this blog post.

Note

This lifecycle was previously named componentWillMount . That name will continue to work until version 17. Use the rename-unsafe-lifecycles codemod to automatically update your components.

UNSAFE_componentWillMount() is invoked just before mounting occurs. It is called before render() , therefore calling setState() synchronously in this method will not trigger an extra rendering. Generally, we recommend using the constructor() instead for initializing state.

Avoid introducing any side-effects or subscriptions in this method. For those use cases, use componentDidMount() instead.

This is the only lifecycle method called on server rendering.

Note

This lifecycle was previously named componentWillReceiveProps . That name will continue to work until version 17. Use the rename-unsafe-lifecycles codemod to automatically update your components.

  • 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 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.

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() .

Note

This lifecycle was previously named componentWillUpdate . That name will continue to work until version 17. Use the rename-unsafe-lifecycles codemod to automatically update your components.

UNSAFE_componentWillUpdate() is invoked just before rendering when new props or state are being received. Use this as an opportunity to perform preparation before an update occurs. This method is not called for the initial render.

Note that you cannot call this.setState() here; nor should you do anything else (e.g. dispatch a Redux action) that would trigger an update to a React component before UNSAFE_componentWillUpdate() returns.

Typically, this method can be replaced by componentDidUpdate() . If you were reading from the DOM in this method (e.g. to save a scroll position), you can move that logic to getSnapshotBeforeUpdate() .

Note

UNSAFE_componentWillUpdate() will not be invoked if shouldComponentUpdate() returns false.

Unlike the lifecycle methods above (which React calls for you), the methods below are the methods you can call from your components.

There are just two of them: setState() and forceUpdate() .

setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. This is the primary method you use to update the user interface in response to event handlers and server responses.

Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. In the rare case that you need to force the DOM update to be applied synchronously, you may wrap it in flushSync , but this may hurt performance.

setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback ( setState(updater, callback) ), 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, read about the updater argument below.

setState() will always lead to a re-render unless shouldComponentUpdate() returns false . If mutable objects are being used and conditional rendering logic cannot be implemented in shouldComponentUpdate() , calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.

The first argument is an updater function with the signature:

state is a reference to the component state at the time the change is being applied. It should not be directly mutated. Instead, changes should be represented by building a new object based on the input from state and props . For instance, suppose we wanted to increment a value in state by props.step :

Both state and props received by the updater function are guaranteed to be up-to-date. The output of the updater is shallowly merged with state .

The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.

You may optionally pass an object as the first argument to setState() instead of a function:

This performs a shallow merge of stateChange into the new state, e.g., to adjust a shopping cart item quantity:

This form of setState() is also asynchronous, and multiple calls during the same cycle may be batched together. For example, if you attempt to increment an item quantity more than once in the same cycle, that will result in the equivalent of:

Subsequent calls will override values from previous calls in the same cycle, so the quantity will only be incremented once. If the next state depends on the current state, we recommend using the updater function form, instead:

For more detail, see:

By default, when your component’s state or props change, your component will re-render. If your render() method depends on some other data, you can tell React that the component needs re-rendering by calling forceUpdate() .

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() .

defaultProps can be defined as a property on the component class itself, to set the default props for the class. This is used for undefined props, but not for null props. For example:

If props.color is not provided, it will be set by default to ‘blue’ :

If props.color is set to null , it will remain null :

The displayName string is used in debugging messages. Usually, you don’t need to set it explicitly because it’s inferred from the name of the function or class that defines the component. You might want to set it explicitly if you want to display a different name for debugging purposes or when you create a higher-order component, see Wrap the Display Name for Easy Debugging for details.

this.props contains the props that were defined by the caller of this component. See Components and Props for an introduction to props.

In particular, this.props.children is a special prop, typically defined by the child tags in the JSX expression rather than in the tag itself.

The state contains data specific to this component that may change over time. The state is user-defined, and it should be a plain JavaScript object.

If some value isn’t used for rendering or data flow (for example, a timer ID), you don’t have to put it in the state. Such values can be defined as fields on the component instance.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *