Параметр селектора изменен, но рендер не вызывается - PullRequest
0 голосов
/ 08 июля 2019
<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>//Reducer
const initialState = {
error: false,
fetching: false,
myData: []
}

export const getDataReducer = (state = initialState, action) => {

switch (action.type) {
    case ActionTypes.MyData.fetch.request:
        return { ...state,
              fetching: true,
              error: false,
              myData: initialState.myData
            }

    case ActionTypes.MyData.fetch.success:
        return {
            ...state,
            myData: action.payload
            fetching: false,
            error: false
        }

    case ActionTypes.MyData.fetch.error:

        return { 
              ...state,
              error: true,
              fetching: false
            }
        }

export const getError = (state) => get(state, 'myData.error', false);

        const mapStateToProps = (state) => {
          return getMyData(state);
        }

        export const getMyData = createSelector(
          [getClientId, getFetching, getError],
          (clientId, fetching, error) => {
            console.log("in selector:", fetching, error)
            const state = store.getState();
            const myData = getData(state);

            let hasErrorOrNoData = error ? error : myData.length === 0;

            hasErrorOrNoData = fetching ? false : hasErrorOrNoData;
            console.log("in selector hasErrorOrNoData:", hasErrorOrNoData)

            return {
              error,
              fetching,
              hasErrorOrNoData,
              myData
            }
          }
        )
        export const DataTable = ({
          error,
          fetching,
          hasErrorOrNoData,
          myData
        }) => {
          console.log("in component this gets called only once")
          return ( <
            componentX rows = {
              myData
            }
            fetching = {
              fetching
            }
            error = {
              hasErrorOrNoData
            }
            errorComponent = { < NoDataMessage
              isError = {
                error
              }
              />
            }
            />
          )
        }

Вопрос : изначально значение ошибки - false, выборка - true.Более поздняя выборка - ложь, а ошибка - истина (поскольку вызов API не удался).Хотя значение выбранных параметров изменилось, почему рендеринг не происходит?Я поместил console.log в render для проверки, но он был выполнен только один раз.

FYI : изменение в fetch и clientId вызывает рендеринг, это только ошибка, которая не срабатывает.

Добавление кода редуктора

Ответы [ 2 ]

0 голосов
/ 10 июля 2019

Реальный виновник был shouldComponentUpdate, условие, написанное в нем, не позволяло отрисовывать. Я полагаю, что документ должен упомянуть то же самое - просто дать подсказку.

0 голосов
/ 08 июля 2019

Уникальным способом обновления вашего кода является то, что ваши реквизиты не меняются .

См. Этот тест:

https://codesandbox.io/embed/friendly-mcclintock-rhwt9?fontsize=14

Перейти к:

function reducer(state = { test: { fixed: "fixed", error: false } }, action) {
  return { test: { fixed: "fixed", error: !state.test.error } };
}

и измените: error: !state.test.error на error: state.test.error, и обновление остановится.

EDIT

В вашем редукторе я вижу:

case ActionTypes.MyData.fetch.error:

        return { 
              ...state,
              error: true,
              fetching: false
            }
        }

И селектор getError равен

export const getError = (state) => get(state, 'myData.error', false);

Но в исходном состоянии: myData - это массив, поэтому myData.error не будет существовать. Ваш селектор getError всегда будет возвращать значение false.

Попробуйте изменить селектор на:

export const getError = (state) => state.error;

...