2015-08-07 8 views
18

Я работал с оптимистическим обновлениями в React + Flux применения и увидел две вещи:Магазин действий для оптимистичных обновлений - хороший подход в Redux/Flux?

  1. Что произойдет, если пользователь пытается закрыть окно, когда существует несколько незавершенных действий. Например, в Facebook сообщение появляется в стене, даже если оно не было действительно сохранено (это то, что оптимистичные обновления делают, более отзывчивое приложение для пользователя). Но, если пользователь поставил в стене и сразу же закрыл приложение (при выходе из системы или закрытии окна), сообщение может потерпеть неудачу, и он не будет предупрежден.
  2. Мне не нравится идея того, что магазины управляют своими сущностями (например, сообщениями) и ситуацией действия, вызванной для продолжения сообщения (загрузка, succesfull, failed?). Он смешивает вещи.

Так я работаю над этим и создать ActionStore для управления состоянием действий, вызванных компонентами. Here is Исходный код и here is живая демонстрация.

Он работает более или менее так:

  1. Корень иерархии компонентов (контейнер в Redux) принести NextID нового действия и передать его свой Чайлдс, как реквизит (это некрасиво).
  2. Детский компонент запускает действие: он сохраняет actionId, чтобы спросить его в магазине после и вызвать создателя действия.
  3. Создатель действия создает новое действие и возвращает функцию промежуточному программному обеспечению.
  4. Функция, возвращаемая из Action, создает новое Promise с вызовом API и отправляет действие типа XX_START.
  5. ActionStore прослушивает действие XX_START и сохраняет его.
  6. Детский компонент получает новое состояние и находит действие с сохраненным идентификатором и задает ему текущую ситуацию: загрузка, успешность или неудача.

Я сделал это в основном для разделения состояния «сущностей» на состояние действий, но также допускает повторные действия с той же полезной нагрузкой (это может быть полезно, когда мы получаем 500 ответов, если сервер временно вниз или если пользователь потерял сигнал).

Кроме того, наличие хранилища действий позволяет легко спросить, находятся ли они в ожидании действий до выхода пользователя из системы или закрытия окна.

Примечание: Я работаю с одним приложением страницы веб-приложение против API Rest, я не думаю, чтобы использовать это на стороне сервера визуализации

Это жизнеспособный вариант создания ActionStore или я ломать некоторые фонды Redux/Flux? Это может привести к возможности использования React Hot Reloading и Time travel?

Вы должны отвечать без пощады, я, вероятно, сделал кучу уродливых вещей, но я изучаю React/Redux.

ответ

21

Для будущих читателей, которые могут быть немного озадачены: мы больше не называем эти функции «магазинами»: мы называем их reducers. Так что вопрос о a reducer remembering actions.

Лично мне не нравится подход, который вы предлагаете там.Вы вводите логику в действия и используете для этого наследование. Напротив, Redux предписывает действия как простые объекты без логики. Они не должны «знать», как обновлять какое-то состояние, и они не должны его удерживать - вместо этого они должны описывать, что произошло.

Я думаю, что подход для реализации оптимистичных обновлений в Redux аналогичен тому, как вы должны были implement Undo in Redux, который, в свою очередь, вдохновлен Elm architecture. Идея заключается в том, что вы должны написать функцию, которая принимает редуктор (некоторые параметры) и возвращает редуктор:

function optimistic(reducer) { 
    return function (state, action) { 
    // do something? 
    return reducer(state, action); 
    } 
} 

Вы бы использовать его как обычный редуктор:

export default combineReducers({ 
    something: optimistic(something) // wrap "something" reducer 
}) 

Прямо сейчас он просто передает состояние и действие на reducer он заворачивает, но она также может «запомнить» действия:

function optimistic(reducer) { 
    return function (state = { history: [] }, action) { 
    // do something with history? 
    return { 
     history: [...state.history, action], 
     present: reducer(state.history[state.history.length - 1], action) 
    }; 
    } 
} 

Теперь он накапливает все действия в history е IELD.

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

  • отслеживает незавершенный асинхронные действия по их идентификаторам и начинается запись истории, когда он видит действие с status: 'request';
  • , когда он получает действие с status: 'done', сбрасывает историю;
  • , когда он получает действие с status: 'fail', настраивает историю, чтобы не включать начальное действие с status: 'request', и повторно запускает редуктор, чтобы пересчитать текущее состояние, как будто запрос никогда не был выполнен.

Конечно, я не представил реализацию, но это должно дать вам представление о том, как реализовать оптимистичные обновления в режиме Redux.

Обновление: согласно комментарию OP, redux-optimist, похоже, делает именно это.

+0

Спасибо за помощь Dan. Я не понимаю, почему вы говорите, что ** редуктор должен пересчитать текущее состояние, как будто запрос никогда не происходил **. Если у меня есть компонент React, который вызвал действие с зависанием загрузки, я хочу показать визуализацию сообщения об ошибке, если действие завершилось неудачно. Если я потеряю действие, как это достичь? На самом деле я использую промежуточное программное обеспечение на основе [redux-prom] (https://github.com/acdlite/redux-promise), я думаю, что это хороший подход к тому, что я пытаюсь достичь, не так ли? ? – gabrielgiussi

+0

«Я не понимаю, почему вы говорите, что редуктор должен пересчитать текущее состояние, как если бы запрос никогда не происходил». Я думал, что вопрос связан с оптимистичными обновлениями. С оптимистичным обновлением вы хотите откатить любую мутацию, которую вы сделали в начале запроса, если она не удалась. Отображение сообщения об ошибке - это несвязанный вопрос с оптимистичными обновлениями; например, http://stackoverflow.com/questions/31822706/how-to-coordinate-server-error-messages-between-flux-and-react/32922286#32922286. –

+0

Вы правы, я немного смутил понятия. Я собираюсь задуматься о вашем предложении и попытаться вернуться с реализацией. Также я рассмотрю [redux-optimist] (https://github.com/ForbesLindesay/redux-optimist), возможно, это то, что я искал. Простое мнение, я думаю, что сообщение об ошибке глубоко связано с оптимистичными обновлениями, если мы хотим выполнить отзывчивость, элемент ToDo не может просто выскочить с экрана. – gabrielgiussi