Функция выбора useSelector неожиданно вызывается при повторном рендеринге - PullRequest
2 голосов
/ 09 апреля 2020

У меня есть простое приложение (просмотр на stackblitz ), использующее useSelector

const TodoList = () => {

  const [count, setCount ] = useState(0);

  const todos = useSelector(state => {
    console.log('useSelector called')
    return state.todos
  });

  useEffect(() => {
  const timer = setInterval(() => {
    setCount(count++)
  }, 1000);
  return () => clearTimeout(timer);
}, []); 
  return <p>{count}</p>
}
export default TodoList

Существует таймер, обновляющий переменную count и отображающий ее в виде , Что я не понимаю, так это то, что функция выбора useSelector вызывается каждый раз, когда F C перерисовывается.

Согласно документам ( или моя интерпретация) это не должно происходить

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

Вопросы

1) как предотвратить повторный запуск селектора?

2) Если моя интерпретация документов неверна, на какую ситуацию ссылаются документы?

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Я думаю, что часть документов может быть немного запутанной. Если вы прочтете немного дальше в документах, это будет немного понятнее https://react-redux.js.org/api/hooks#equality -сравнения и обновления

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

Поскольку у вашего селектора нет зависимостей закрытия, вы можете определить его вне вашего компонента. Что-то вроде:

const todosSelector = state => state.todos

const TodoList = ({ todos, toggleTodo }) => {
  ...
  const todos = useSelector(todosSelector)
  ...
}

У вас также есть возможность использовать useMemo или useCallback, если по какой-то причине вам нужно определить его в вашем компоненте.

0 голосов
/ 09 апреля 2020

Ваш счетчик является состоянием использования. Каждый раз, когда это состояние изменяется, этот компонент будет перерисовываться (и затем ваша функция useSelector, совпадающая с do c), вызывая повторный запуск useEffect и снова вызывая таймер. Если вы хотите предотвратить такое поведение, попробуйте извлечь эту функцию в другой компонент, на который не повлияет повторный рендеринг, вызванный изменением состояния вашего счета со временем.

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