Как redux определяет, какие компоненты нужно обновить при изменении состояния в хранилище?

Как правильно привязать Redux к компонентам, используя хук `useSelector` для доступа к состоянию в коде? Я понимаю, что Redux создает объект-обертку в компоненте с помощью `<Provider store={store}>` и хранит набор свойств, откуда берется значение `counter`. Однако, как Redux понимает, в каких компонентах находятся наши селекторы, если мы не указываем это в редьюсерах? И каким образом он обновляет компоненты?
  • 13 января 2024 г. 20:27
Ответы на вопрос 2
Когда вы используете Redux в связке с хуком `useSelector`, происходит следующее:

1. Вы помещаете Redux `Provider` в корень вашего приложения, передавая ему ваш `store`. Это устанавливает контекст, который делает Redux-хранилище доступным для всех компонентов в дереве компонентов вашего приложения.

2. Компонент вызывает `useSelector` хук, который принимает функцию селектора. Селектор функционирует как подписка на определённые части состояния хранилища Redux: он определяет, какие именно данные из общего состояния вам нужны в вашем компоненте.

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

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

Как правильно использовать `useSelector`:

```jsx
import React from 'react';
import { useSelector } from 'react-redux';

export function MyComponent() {
  // Селектор – это просто функция, которая "выбирает" часть состояния.
  // Этот хук автоматически подпишет ваш компонент на обновления
  // соответствующего среза состояния, используемого селектором.
  const someData = useSelector((state) => state.someSlice.someData);

  return (
    <div>{someData}</div>
  );
}
```

В этом примере, когда `state.someSlice.someData` изменится, `useSelector` выполнит селектор и, если результат отличается от предыдущего, вызовет перерисовку `MyComponent`.

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

Реакт и Redux используют механизм подписок и сравнений, чтобы минимизировать количество ненужных перерисовок. Это особенно важно в крупных и сложных приложениях, где изменение одного среза состояния не должно приводить к глобальной перерисовке.
useSelector внутри себя использует хук useSyncExternalStore (точнее, хук, аналогичный ему) 

вкратце суть работы: из редуксового контекста (того самого, который использован внутри Provider) достается редуксовый же стор. Этот стор постоянный, но в нем есть состояние - объект, ссылка на который меняется при каждом изменении, ибо иммутабельность. Подписываемся на изменение этой ссылки (т.е. по факту на изменение любой части состояния), у стора есть метод subscribe для этого. При срабатывании эвента забираем наши данные селектором, и если результат селектора отличается от предыдущего раза, значит изменились именно наши данные и надо пнуть компонент, чтобы обновился, это уже useSyncExternalStore знает как сделать.
Похожие вопросы