Подтвердить что ты не робот

Переход на другой маршрут при успешном действии async redux

У меня довольно простой набор реагирующих компонентов:

  • container, который перехватывает redux и обрабатывает действия, сохраняет подписки и т.д.
  • list, который отображает список моих элементов.
  • new, который является формой для добавления нового элемента в список

У меня есть маршрут react-router следующим образом:

<Route name='products' path='products' handler={ProductsContainer}>
  <Route name='productNew' path='new' handler={ProductNew} />
  <DefaultRoute handler={ProductsList} />
</Route>

чтобы показать либо list, либо form, но не оба.

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

Моим решением до сих пор является .then() после async dispatch:

dispatch(actions.addProduct(product)
  .then(this.transitionTo('products'))
)

Это правильный способ сделать это или мне нужно каким-то образом запустить другое действие, чтобы вызвать изменение маршрута?

4b9b3361

Ответ 1

Если вы не хотите использовать более полное решение, например Redux Router, вы можете использовать Redux History Transitions, который позволяет вам писать код следующим образом:

export function login() {
  return {
    type: LOGGED_IN,
    payload: {
      userId: 123
    }
    meta: {
      transition: (state, action) => ({
        path: `/logged-in/${action.payload.userId}`,
        query: {
          some: 'queryParam'
        },
        state: {
          some: 'state'
        }
      })
    }
  };
}

Это похоже на то, что вы предложили, но немного сложнее. Он по-прежнему использует ту же библиотеку history под капотом, чтобы она совместима с React Router.

Ответ 2

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

import history from "../routes/history";

export default store => next => action => {

    if ( ! action.redirect ) return next(action);

    history.replaceState(null, action.redirect);
}

Итак, оттуда вам нужно убедиться, что ваши действия successful имеют свойство redirect. Также обратите внимание, что это промежуточное ПО не запускает next(). Это специально, так как переход маршрута должен быть завершением цепочки действий.

Ответ 3

Для тех, кто использует слой API промежуточного программного обеспечения, чтобы абстрагировать их использование чего-то вроде isomorphic-fetch, а также использовать redux-thunk, вы можете просто отключить свой dispatch Promise внутри своих действий, например:

import { push } from 'react-router-redux';
const USER_ID = // imported from JWT;

function fetchUser(primaryKey, opts) {
    // this prepares object for the API middleware
}

// this can be called from your container
export function updateUser(payload, redirectUrl) {
    var opts = {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
    };
    return (dispatch) => {
        return dispatch(fetchUser(USER_ID, opts))
            .then((action) => {
                if (action.type === ActionTypes.USER_SUCCESS) {
                    dispatch(push(redirectUrl));
                }
            });
    };
}

Это уменьшает необходимость добавления библиотек в ваш код, как предлагается здесь, а также красиво совмещает ваши действия с их перенаправлением, как это сделано в redux-history-transitions.

Вот как выглядит мой магазин:

import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../reducers';
import thunk from 'redux-thunk';
import api from '../middleware/api';
import { routerMiddleware } from 'react-router-redux';

export default function configureStore(initialState, browserHistory) {
    const store = createStore(
        rootReducer,
        initialState,
        applyMiddleware(thunk, api, routerMiddleware(browserHistory))
    );

    return store;
}

Ответ 4

Я знаю, что я немного опаздываю на вечеринку, так как реакция-навигация уже включена в документацию, предназначенную для реагирования, но все же она может быть полезна для пользователя, который использовал/использовал Navigator api в своих приложениях. то, что я пробовал, немного хакерский, я сохраняю экземпляр навигатора в объекте, как только renderScene происходит -

renderScene(route, navigator) {
      const Component = Routes[route.Name]
      api.updateNavigator(navigator); //will allow us to access navigator anywhere within the app
      return <Component route={route} navigator={navigator} data={route.data}/>

}

my api файл - это что-то lke this

'use strict';

//this file includes all my global functions
import React, {Component} from 'react';
import {Linking, Alert, NetInfo, Platform} from 'react-native';
var api = {
    navigator,
    isAndroid(){
        return (Platform.OS === 'android');
    },
    updateNavigator(_navigator){
      if(_navigator)
          this.navigator = _navigator;
    },
}

module.exports = api;

теперь в ваших действиях вы можете просто вызвать

api.navigator.push({Name: 'routeName', данные: WHATEVER_YOU_WANTED_TO_PASS)

вам просто нужно импортировать api из модуля.