React-Redux: каково подходящее начальное состояние для флага выборки?

#reactjs #redux #react-redux

#reactjs #сокращение #react-redux

Вопрос:

Я внедрил флаг выборки, который указывает, извлекаются ли данные в данный момент или нет. Флаг выборки работает нормально и переходит от isFetching = false к isFetching = true и обратно, как и должно быть. Но у меня возникли проблемы с выяснением, каким должно быть начальное состояние флага выборки? Оба isFetching = true и isFetching = false приводят к нежелательному поведению.

Вариант 1:

В случае, если флаг выборки имеет значение true:

const initialState = { isFetching: true };

… и я пытаюсь отобразить некоторые данные на основе флага выборки:

{!isFetching === false? <LoadedComponent props ={data} /> : <LoadingSpinner />

все работает нормально. Однако после очистки состояния redux, например, после выхода пользователя из системы, falg выборки снова переходит в true. Сохранение приложения в состоянии загрузки.

 isFetching: true
isFetching: true
isFetching: false
isFetching: true // <- after clearing store, jumps into loading state and remains there. e.g. causing for a not logged in user a loading state 

  

Вариант 2:

В случае, если флаг выборки равен false:

const initialState = { isFetching: false };

… и я пытаюсь отобразить некоторые данные на основе флага выборки…

{!isFetching === false? <LoadedComponent props ={data} /> : <LoadingSpinner />

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

 isFetching: false // <- trys to render but data not ready.
isFetching: true
isFetching: false
isFetching: false 
  

Оба варианта на самом деле не подходят в моем случае. Итак, как я должен установить свой начальный флаг выборки, чтобы избежать такого поведения? Я рад любым разъяснениям.

Ответ №1:

Вот почему мы рекомендуем рассматривать состояние загрузки как «конечный автомат», предпочтительно с перечислением для значения состояния загрузки:

 interface ItemsState {
  items: Item[];
  status: 'idle' | 'loading' | 'succeeded' | 'failed'
}
  

Таким образом, вы можете отличить «мы еще не пытались его извлечь» от «мы пытались и добились успеха / потерпели неудачу».

Смотрите страницу руководства Redux Essentials «Асинхронная логика и выборка данных» для примеров этого в действии.

Ответ №2:

Не пытайтесь инкапсулировать три или более элемента в логическую переменную. Выборка означает выборку и ничего больше. Вы не можете вывести что-либо еще из этого состояния.

 const initialState = {
  fetching: false,
  error: null,
  data: null
};

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case Actions.FETCH_PENDING: {
      return { ...state, fetching: true, error: null };
    }
    case Actions.FETCH_SUCCESS: {
      return { ...state, fetching: false, data: action.data, error: null };
    }
    case Actions.FETCH_REJECTED: {
      return { ...state, fetching: false, error: action.error, data: null };
    }

    default:
      return state;
  }
};
  

Как писал маркериксон, обычно существует 4 состояния, которые вы должны каким-то образом отобразить: бездействие, ожидание, успешное выполнение, сбой. Простой обычно возникает только при монтировании компонента. Вот пример приложения, которое запрашивает шутки из конечной точки:

 function App({ joke, fetching, error, fetchJoke }) {
  return (
    <div className="App">
      <button onClick={() => fetchJoke()} disabled={fetching}>
        add a thing
      </button>

      {fetching ? (
        <span>Loading...</span>
      ) : joke ? (
        <p>Joke: {joke}</p>
      ) : error ? (
        <strong>{error}</strong>
      ) : (
        <span>Idle: Click to load a joke</span>
      )}
    </div>
  );
}