Почему этот селектор повторного выбора вызвал повторную визуализацию? - PullRequest
0 голосов
/ 08 мая 2020

Один из моих компонентов перерисовывал, и я понял, что это из-за селектора allPageViews ниже:

const getPages = (state: IAppState) => {
  return state.pages;
};


export const attachPageViews = createSelector(
  getPages,
  (pages) => pages.pageViews
);
export const selectPageViews = createSelector(
  attachPageViews,
  (pageViews) => pageViews
);


export const allPageViews = createSelector(
  selectPageViews,
  (pageStore: PageViewStore) => {
    let returnedPageViews: PageView[] = [];
    for (const section of Object.values(pageStore.sections)) {
      for (const page of Object.values(section!.pageViews)) {
        returnedPageViews = [...returnedPageViews, page!];
      }
    }
    return returnedPageViews;
  }
);

Когда я отправлял действие, я менял редуктор страниц, но не pageViews содержащиеся внутри (у страниц есть другой ключ, называемый данными, которые я обновлял). Итак, насколько я понимаю, selectPageViews не должен изменяться (потому что базовые pageViews не меняются), и поэтому allPageViews должны просто запоминать, а не пересчитывать, потому что ничего не было обновлено. Когда я переместил массив returnPageViews и циклы for в компонент, который использовал useSelector (), компонент перестал перерисовывать.

Итак, мой вопрос - как работает Reselect и почему он пересчитывал и вызвать повторную визуализацию, когда массив создавался в allPageViews?

1 Ответ

0 голосов
/ 01 июня 2020

Я менял редуктор страниц, но не элементы pageView, содержащиеся внутри (страницы имеют другой ключ, называемый данными, которые я обновлял). Итак, насколько я понимаю, selectPageViews не должен меняться (потому что базовые pageViews не меняются), и поэтому allPageViews должны просто запоминать, а не пересчитывать, потому что ничего не было обновлено.

Это правильно, состояние. page.pageViews не изменился, поэтому selectPageViews вернет мемоизированный результат, как и allPageViews.

Тем не менее, вычисление производилось повторно. Когда я переместил массив returnPageViews и циклы for в компонент, который использовал useSelector (), компонент прекратил повторный рендеринг . Итак, мой вопрос: как работает Reselect, и почему он пересчитал и запустил повторную визуализацию , когда массив создавался в allPageViews?

Это не делает смысл, значит селектор не запускает повторный рендеринг? И Nonetheless it was re-calculating неверно, вот ваш код ниже, демонстрирующий, что ваше первоначальное предположение было правильным; если вы не измените state.page.pageViews, тогда как selectPageViews, так и allPageViews вернут свой мемоизированный результат (пересчет не будет):

const { createSelector } = Reselect;
const getPages = (state) => {
  return state.pages;
};

const attachPageViews = createSelector(
  getPages,
  (pages) => pages.pageViews
);
//this one is kind of useless, it does x=>x so you may as
//  well do: const selectPageViews = attachPageViews
const selectPageViews = createSelector(
  attachPageViews,
  (pageViews) => {
    console.log(
      'selectPageViews logs once but is called twice'
    );
    return pageViews;
  }
);

const allPageViews = createSelector(
  selectPageViews,
  (pageStore) => {
    console.log(
      'allPageViews logs once but is called twice'
    );
    return { new: 'object', pageStore };
  }
);
const state = {
  pages: {
    pageViews: { value: 'this is page views' },
  },
};
console.log('calling allPageViews first time');
const one = allPageViews(state);
console.log('calling allPageViews second time with changed state.pages');
const two = allPageViews({
  ...state,
  pages: {
    ...state.pages,
    changedSomething: true,
  },
});
console.log('both results are the same:',one === two);
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>


<div id="root"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...