Как отправить переменные побочные эффекты в Redux - PullRequest
0 голосов
/ 12 октября 2018

В моем проекте TypeScript я предоставляю пользователю диалог ветвления.Отображается текст, и пользователю предоставляются параметры, которые затем вводят новую ветвь.С каждой веткой может быть связан один или несколько Action, которые не имеют ничего общего с Redux.Мы назовем эти MyAction s для ясности.

MyAction s довольно универсальны, вы можете выбрать тип действия и аргументы для передачи вместе с ним.Действие соответствует функции, зарегистрированной в ActionParser, которая отвечает за выполнение этих MyAction s.

Одним из наиболее важных MyAction s является действие LOAD_SCENE, которое позволяетПользователь переключается на совершенно другую сцену.Сцена сначала загружается с сервера, а затем представляется пользователю в корневой ветви дерева диалога.Именно здесь начинаются проблемы.

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

Это происходит следующим образом:

  1. Пользователь щелкает[button] в пользовательском интерфейсе
  2. Кнопка запускает mapDispatchToProps.onButtonClick
  3. onButtonClick вызывает функцию, которая обновляет SceneParser с новой ветвью.
  4. С выбранной новой ветвью отправляется onButtonClickвызывается действие PARSING_START
  5. SceneParser.parseActiveBranch, в котором выполняются действия.Здесь происходят побочные эффекты.
  6. Наконец, вызывается PARSING_SUCCESS и вызывается SCENE_UPDATE для отображения нового диалога и параметров

На шаге 5 выполняются действия.Действие LOAD_SCENE выглядит следующим образом:

ActionParser.register("LOAD_SCENE", async (args) => {
    if (args.scene) {
        Store.get().dispatch(loadSceneStart());
        await SceneManager.loadScene(args.scene);
        Store.get().dispatch(loadSceneSuccess(SceneManager.activeScene.author));
    } else {
        throw new Error("action 'LOAD_SCENE' requires 'scene' argument");
    }
});

Проблемы очевидны:

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

MyAction s всегда запускаются как часть бизнес-логики.Поскольку они могут иметь побочные эффекты, я хочу, чтобы результаты моих действий влияли на состояние, но в то же время я не хочу отправлять их из действия.Вот функция dispatch, которая делает все это.

public static onSelectOption(dispatch: Dispatch, branch: string) {
    try {
        SceneManager.selectBranch(branch); // MyActions are processed here. Side effects of MyActions may have happened.

        // These fire immediately because some MyActions may be asynchronous.
        if (SceneManager.sceneIsFinished) {
            dispatch(setMode(Mode.MainMenu));
        } else {
            dispatch(updateScene(SceneManager.dialogue, SceneManager.options));
        }
    } catch (error) {
        dispatch(setGameView(View.Error));
        dispatch(setError(error.stack || error.message));
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...