web-dev-qa-db-ja.com

成功した非同期reduxアクションでの別のルートへの移行

反応コンポーネントの非常に単純なセットがあります。

  • containerredux にフックし、アクション、ストアサブスクリプションなどを処理します
  • listは私のアイテムのリストを表示します
  • newは、新しいアイテムをリストに追加するフォームです

次のような react-router ルートがいくつかあります。

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

listまたはformのいずれかが表示されますが、両方は表示されません。

私がやりたいのは、新しいアイテムが正常に追加されたら、アプリケーションをリストに再ルーティングすることです。

これまでの私の解決策は、非同期dispatchの後に.then()を持つことです。

_dispatch(actions.addProduct(product)
  .then(this.transitionTo('products'))
)
_

これはこれを行う正しい方法ですか、ルート変更をトリガーするために何らかの方法で別のアクションを起動する必要がありますか?

57
Clarkie

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と互換性があります。

28
Dan Abramov

私は最終的にそのように見える非常にシンプルなミドルウェアを作成することになりました:

_import history from "../routes/history";

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

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

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

したがって、そこからsuccessfulアクションにredirectプロパティがあることを確認するだけです。また、このミドルウェアはnext()をトリガーしません。これは、ルート遷移がアクションチェーンの最後にある必要があるためです。

25
silkAdmin

ミドルウェアAPIレイヤーを使用して isomorphic-fetch などの使用を抽象化し、またたまたま redux-thunk を使用している場合は、単にdispatch次のように、アクション内で約束します。

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));
                }
            });
    };
}

これにより、提案された here のようにコードにライブラリを追加する必要が減り、 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;
}
18
Cameron

反応ナビゲーションは既に反応ネイティブのドキュメントに含まれているので、私はパーティーに少し遅れていることを知っていますが、それでもアプリで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}/>

}

私のAPIファイルはこれのようなものです

'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'、data:WHATEVER_YOU_WANTED_TO_PASS)

モジュールからAPIをインポートするだけです。

0
Manjeet Singh

react-redux および react-router を使用している場合、 このリンク が優れたソリューションを提供すると思います。

私が使用した手順は次のとおりです。

  • コンポーネントを反応ルーター_<Route/>_コンポーネント内にレンダリングするか、historyを使用して高次コンポーネントを作成することにより、反応ルーターwithRouter propをコンポーネントに渡します。
  • 次に、リダイレクトしたいルートを作成します(私はtoと呼びました)。
  • 3番目に、historytoの両方でreduxアクションを呼び出します。
  • 最後に、リダイレクトしたいとき(たとえば、reduxアクションが解決したとき)、history.Push(to)を呼び出します。
0
Brad W