Является ли плохой практикой сохранение сильного состояния, связанного с пользовательским интерфейсом, внутри компонента реакции?

Я переношу свое приложение reactJs на redux/mobx. На данный момент у меня есть 3 компонента, каждый из которых имеет в своем состоянии следующую структуру:

name:string,
surname:string,
showError: boolean,
loading:boolean

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

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

Итак, моя идея заключается в следующем:

this.state = {showError, loading};
this.businessState = props.state;

Короче говоря, я продолжу обновлять «состояние» с помощью функции React setState(), оставив redux/mobx управление так называемым «бизнес-состоянием».

Может ли это быть хорошей практикой или я делаю что-то особенно плохое?

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

Estus Flask 09.04.2019 11:41
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
3
1
515
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

У меня лично нет проблем с этим, поскольку «загрузка» и «showError» относятся к состоянию, а не к компоненту пользовательского интерфейса. По сути, это говорит о том, что когда я заполняю свое состояние из вызова API, это уже сделано и что-то пошло не так? Компонент пользовательского интерфейса отображается соответствующим образом.

Я бы сделал showError строкой или строкой [] в зависимости от структуры ошибок, выдаваемых вашей системой BE.

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

Я надеюсь, что это поможет в некотором роде.

Ответ принят как подходящий

Лично я бы посоветовал сделать store для большинства components, и, исходя из моего опыта, большинство stores на самом деле являются ViewStore's. Если у вас есть похожая логика, такая как loading и errors на нескольких components, то сделать что-то вроде этого еще проще:

class BaseViewStore {
    @observable loading = false
    @observable showError = false
}

Тогда ваш component store просто расширит этот store, и у вас будет многоразовая логика внутри этого base store. Все, что является component конкретным, конечно же, пойдет в этом конкретном store. Таким образом, ваш components будет чистым, не будет иметь personal state (внутри самого component) и его можно будет легко заменить другими компонентами, поскольку ваше поведение (состояние) будет в stores.

Я не уверен, что это лучшая практика или нет. Но состояние загрузки используется, когда вы выполняете какое-либо асинхронное действие, например, получаете данные из API. Лучшая практика для получения таких данных — это действие. И то, что я обычно делаю внутри действия, — это отправка состояния загрузки перед вызовом API и отправка редюсера, который устанавливает для загрузки значение false после получения данных.

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

Это было бы что-то вроде этого

action.js

getData = () => {
   return (dispatch) => {
      dispatch({ type: LOADING });
      callApiToGetData()
         .then(data => {
            dispatch({ type: SUCCESS, data })
         })
         .catch(e => {
            dispatch({ type: ERROR, error: e })
         })
   }
}

редуктор.js

const initialState = {
  data: null,
  loading: false,
  error: null
}

function reducer(state = initialState, action) {
  switch (action.type) {
    case LOADING:
       return { ...state, loading: true }
    case SUCCESS:
       return { ...state, loading: false, data: action.data, error: null }  
    case FAIL:
       return { ...state, loading: false, error: action.error }
    default:  
       return state
}

Можно ли использовать async/await внутри редукторов? Или меня заставляют этим фрагментом с обещаниями? Я спрашиваю, потому что сейчас я использую mobx и не очень разбираюсь в редукции.

Phate 14.04.2019 17:52

Можно использовать async/await в действии (не редуктор. Редуктор предназначен только для сопоставления данных после бизнес-логики из действия). Просто убедитесь, что вы используете версию babel и ecmascript, которую вы используете, поддерживает ее.

Dat Tran 15.04.2019 09:19

лишь бы добавить. Вам нужно использовать redux-thunk, чтобы сделать возможным выполнение таких асинхронных действий.

Dat Tran 15.04.2019 09:27

Другие вопросы по теме