useSelector перехватывает и рендеринг - PullRequest
3 голосов
/ 16 марта 2020

- изменить - я создал коды и поле: https://codesandbox.io/s/xenodochial-hofstadter-d3jjo

Я начинаю чесать голову и хотел бы помочь - я предполагаю - простая проблема.

У меня есть базовый c компонент приложения, который выполняет контролируемый ввод текста. Как только вы отправляете этот ввод, он создает сообщение на бэкэнде, которое обновляет хранилище редуксов. В этой части все работает нормально.

Моя проблема в том, что я пытался добавить хук useEffect для сброса входного значения после добавления нового сообщения. Я заметил, что useEffect, основанный на [messages], вызывается при каждом рендеринге, а не только когда messages изменяется. Простое действие ввода во входных данных - которое вызывает повторное отображение для каждого символа - приводит к срабатыванию триггера, даже если это все то же значение: пустой массив.

В основном я заметил, что это работает только как предназначен, если мой useSelector возвращает тот же экземпляр массива. Так что, если бы я только для чтения state.messages.allIds, это работало бы, так как массив не меняется. Но простое добавление .map(x => x) заставляет его каждый раз возвращать новый экземпляр. Я добавил shallowEqual response-redux, чтобы попытаться это исправить, но безрезультатно, и я не понимаю, почему это не решает мою проблему.

const App = () => {
  const [message, setMessage] = useState('');
  const messages = useSelector(
    (state: RootState) => (
      state.messages.allIds.map((id: string) => state.messages.byId[id])
    ),
    shallowEqual,
  );

  useEffect(() => {
    console.log('useEffect');
  }, [messages]);

  // ...

  return (
    <form onSubmit={/* ... */}>
      <input
        onChange={event => setMessage(event.target.value)}
        value={message}
      />
    </form>
  );
}

1 Ответ

4 голосов
/ 16 марта 2020

Может быть, вы можете использовать useMemo?

 const messages = useSelector(
    (state: RootState) => (
      state.messages
    )
  );

 let mapped  = useMemo(() => messages.allIds.map((id: string) => messages.byId[id]), [messages]);

Используйте mapped теперь везде.

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