Почему useDispatch повторно отображает родительские компоненты? - PullRequest
4 голосов
/ 04 марта 2020

Я использую ловушку useDispatch (из Redux) в обратном вызове onSelect в компоненте Tree (из библиотеки Ant):

export const MyComponent = () => {

    const dispatch = useDispatch();

    const onSelect = (selectedNode) => {
            const selectedItem = selectedNode[0];
            dispatch(fetchSelectedItems(selectedItem));
    };

    return 
        <Tree
            onSelect={onSelect}
        >
            <TreeNode .. />
            <TreeNode .. />
            <TreeNode .. />
        </Tree
}


export const fetchSelectedItems = (selected: string) =>
    (dispatch) =>
        axios({
            url: `/api/items?id=${selected}`,
            method: 'GET',
        }).then(response => {
            dispatch(fetchSelectedItemsSuccess(response.data))
        }).catch((error: any) => {throw(error)});

Почему useDispatch повторно отображает родительские компоненты? Есть ли способ предотвратить это? Я попытался useCallback, как это указано в документации Redux, но это решение - для предотвращения повторного рендеринга дочерних компонентов, а не родителей.

Ответы [ 3 ]

1 голос
/ 04 марта 2020

Похоже, мое предположение в комментарии было верным.

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

Это изолирует обновление только до ClickValue компонента.

Мой форк: https://codesandbox.io/s/soanswer60515755-9cc7u

function ClickValue() {
  const clickValue = useSelector(state => state.value);
  console.log(clickValue);
  return clickValue;
}

export default function Container() {
  return (
    <div className="Container">
      <h3>Container</h3>
      <ParentComponent />
      <ClickValue />
    </div>
  );
}

Проверьте приведенный ниже профиль.

profile result

0 голосов
/ 07 марта 2020

Моя проблема с компонентами повторного рендеринга была вызвана useSelector, использованным в родительских компонентах, где я непосредственно ссылаюсь на state. Скорее всего, из-за нового результата этого селектора.

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

0 голосов
/ 04 марта 2020

Я думаю, что при каждом рендеринге вы переделываете функцию onSelect. Функции являются ссылочными типами. Передача этой повторно объявленной функции с ее новой ссылкой при любом рендере вызовет рендеринг. Возможно, вам стоит изучить контекст.

...