Бизнес-логика приложения Redux, которая не влияет на состояние?

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

Документация и другие источники, похоже, утверждают, что бизнес-логика должна идти либо в создателях действий, либо в редукторе. Однако у меня есть функция login(), которая никоим образом не меняет состояние, она сохраняет текущее состояние приложения как простой объект в localStorage, а затем перенаправляет пользователя на сервер авторизации. Когда пользователь вошел в систему и был перенаправлен обратно, состояние восстанавливается (другим фрагментом кода) и передается в качестве начального состояния моей функции создателя магазина.

Мой вопрос: логика функции login просто извлекает состояние, но никоим образом не меняет его, поэтому оно не принадлежит редуктору. Он также не возвращает действие, которое является определением создателя действия. Где в структуре моего приложения я должен его разместить?

"Нормально" иметь создателя действия, который на самом деле не создает действие? Я делаю это прямо сейчас с помощью redux-thunk (потому что мне нужно getState()), и он работает без каких-либо проблем, но это кажется неправильным, потому что на самом деле это не «создатель действий», с другой стороны, у меня также есть logout() функция, которая действительно возвращает действие, поэтому кажется, что они должны жить в одном месте. Я предполагаю, что это своего рода угловой случай, но не совсем потому, что я могу придумать множество причин, чтобы сохранить состояние таким образом и перенаправить посетителей на другие сайты (или даже просто сохранить состояние без перенаправления).

PS. Я знаю, что есть библиотеки для автоматической синхронизации моего хранилища redux с localStorage, но вопрос не в этом.

РЕДАКТИРОВАТЬ: Некоторые пояснения:

Из документации Redux, где разместить бизнес-логику: Нет однозначного ответа на вопрос, какие именно элементы логики должны входить в редюсер или создатель действий.

Читая дальше, становится ясно, что есть только два места, куда я должен поместить бизнес-логику: либо в редьюсере, либо в создателе действий. Теперь, поскольку то, что я хочу сделать, не влияет на состояние, а редуктор по определению влияет на состояние, я склоняюсь к тому, чтобы поместить эту логику в создатель действий.

Документация по создателям действий: Создатели действий - это именно те функции, которые создают действия. Термины «действие» и «создатель действия» легко объединить, поэтому постарайтесь использовать правильный термин. [...] В Redux создатели действий просто возвращают действие

Документация по действиям: Действия - это простые объекты JavaScript.

Псевдокод для моего примера входа в систему:

function login() {
    // retrieving and serializing the state, then:
    localStorage.set('my_app_id_state', my_serialized_state);
    window.location = url_to_authorization_service;
}

Очевидно, этому коду нет места в создателе действия, потому что я не возвращаю действие, что является целью создателя действия. Однако мне все еще нужно получить состояние, поэтому я тоже не могу сделать его полностью независимым.

Итак, опять же, вопрос в том, где мне поместить этот фрагмент кода в структуру моего приложения?

Опять же, код работает, и все в порядке, так что я думаю, это скорее академический вопрос, но меня очень беспокоит то, что я здесь явно нарушаю основные правила Redux. Может это просто исключение?


person Sebastian    schedule 15.06.2016    source источник


Ответы (2)


Это был хороший вопрос, и он заставил меня понять, что я делаю что-то не так. Надеюсь, этот ответ будет полезен, по крайней мере, обоим :)

Возьмите этот пример, адаптированный из Real World Redux. пример:

Частная функция

function oauth(url) {
 return (dispatch) => {
   dispatch({
    type: types.OAUTH_LOGIN,
    url
   });
 };
}

вызывается создателем действия (который возвращает функцию)

export function loginToApi(redirectUrl) {
  return (dispatch) => {
    return dispatch(oauth(redirectUrl))
  }
}

Затем действие, в свою очередь, вызывается в компоненте, например:

login() {
 return this.props.dispatch(loginToApi());
}

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

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

Что касается вашей логики входа в систему для хранения состояния в локальном хранилище: я не думаю, что вам это нужно. Магазин Redux управляет состоянием за вас.

person U r s u s    schedule 15.06.2016
comment
Привет, спасибо, что нашли время ответить. Прошу прощения, если мой вопрос запутал, я пытаюсь привести пример, когда мне нужно сделать что-то в моем приложении, которое не влияет на его состояние. Из документации Redux: Действия - это полезные данные, которые отправляют данные из вашего приложения в ваш магазин. [...] Действия - это простые объекты JavaScript. Действия должны иметь свойство типа ... В вашем примере вы не возвращаете простой объект, и я не делаю этого в своей функции входа в систему. Таким образом, ни один из нас не следит за спецификацией того, каким на самом деле должно быть действие, и в этом проблема :) - person Sebastian; 16.06.2016
comment
Я сейчас отредактировал свой вопрос, может теперь понятнее, о чем я спрашиваю. - person Sebastian; 16.06.2016
comment
Ха, хорошее замечание! Разрешите отредактировать свой ответ. А пока вы видели этот - person U r s u s; 16.06.2016
comment
Спасибо, но не думаю, что становлюсь мудрее. Создатели асинхронных действий на самом деле не возвращают простые объекты, поэтому я думаю, что, возможно, мне следует прочитать документы как правила для чистого приложения redux, то есть без какого-либо промежуточного программного обеспечения, но это звучит странно, поскольку промежуточное программное обеспечение является одной из самых мощных функций Redux (очень мало случаев, когда вам вообще не нужно никакого промежуточного программного обеспечения). И, в конце концов, создатель асинхронного действия вызывает других создателей действий и в конечном итоге эффективно выполняет то, что он должен, - отправляет действия простого объекта, которые влияют на состояние. - person Sebastian; 16.06.2016
comment
Пожалуйста, проверьте мой отредактированный ответ. Вам не нужно использовать промежуточное ПО. Это рекомендуется, только если вы связываете асинхронные действия. - person U r s u s; 16.06.2016
comment
Я видел ваш отредактированный ответ, но зачем мне отправлять действие? Мне не нужно заставлять редуктор реагировать, и это цель диспетчеризации действий (также см. Мой предыдущий комментарий). Также мне нужно использовать thunk или подобное промежуточное ПО, чтобы вернуть функцию от создателя действия. - person Sebastian; 16.06.2016
comment
Здесь я могу только порекомендовать не воспринимать правила слишком буквально; извините, я ничем не могу больше помочь. - person U r s u s; 16.06.2016
comment
Нет проблем, спасибо за обсуждение. Я написал в Твиттере Дэну Абрамову, надеюсь, он это увидит. Но да, я пока буду продолжать нарушать правила. - person Sebastian; 16.06.2016

Дэн Абрамов ответил в твиттере, я сделаю вывод, что это исключение из правил, изложенных в документации. .

Ответ Дэна Абрамова

person Sebastian    schedule 16.06.2016