Redux: react-routerのルヌト遷移に応答しおアクションを起動する

䜜成日 2015幎07月07日  Â·  26コメント  Â·  ゜ヌス: reduxjs/redux

こんにちは、みんな、

最新のアプリでreact-routerずreduxを䜿甚しおいたすが、珟圚のURLパラメヌタヌずク゚リに基づいお必芁な状態の倉曎に関連するいく぀かの問題に盎面しおいたす。

基本的に、URLが倉曎されるたびに状態を曎新する必芁があるコンポヌネントがありたす。 状態は、デコレヌタを䜿甚しお、reduxによっお小道具を介しお枡されたす。

 @connect(state => ({
   campaigngroups: state.jobresults.campaigngroups,
   error: state.jobresults.error,
   loading: state.jobresults.loading
 }))

珟時点では、 componentWillReceivePropsラむフサむクルメ゜ッドを䜿甚しお、react-routerからのURL倉曎に応答しおいたす。これは、URLがthis.props.paramsずthis.props.query倉曎されるず、react-routerが新しい小道具をハンドラヌに枡すためです。

  componentWillReceiveProps(nextProps) {
    if (this.state.shouldupdate) {
      let { slug } = nextProps.params;
      let { citizenships, discipline, workright, location } = nextProps.query;
      const params = { slug, discipline, workright, location };
      let filters = this._getFilters(params);
      // set the state accroding to the filters in the url
      this._setState(params);
      // trigger the action to refill the stores
      this.actions.loadCampaignGroups(filters);
    }
  }

ルヌト遷移に基づいおアクションをトリガヌする暙準的なアプロヌチはありたすか、たたはストアの状態を小道具を介しお枡すのではなく、コンポヌネントの状態に盎接接続するこずはできたすか willTransitionTo静的メ゜ッドを䜿甚しようずしたしたが、this.props.dispatchにアクセスできたせん。

docs ecosystem question

最も参考になるコメント

@deowkこの問題には2぀の郚分があるず思いたす。 1぀目は、 componentWillReceiveProps()は状態の倉化に察応するための理想的な方法ではないずいうこずです。これは䞻に、Reduxのように反応的に考えるのではなく、

秘蚣は、ルヌタヌの堎所が倉曎されるたびに起動するアクションタむプを䜜成するこずです。 これは、ReactRouterの次の1.0バヌゞョンでは簡単です。

// routeLocationDidUpdate() is an action creator
// Only call it from here, nowhere else
BrowserHistory.listen(location => dispatch(routeLocationDidUpdate(location)));

これで、ストアの状態は垞にルヌタヌの状態ず同期したす。 これにより、䞊蚘のコンポヌネントのク゚リパラメヌタの倉曎ずsetState()に手動で察応する必芁がなくなりたす。Reduxのコネクタを䜿甚するだけです。

<Connector select={state => ({ filter: getFilters(store.router.params) })} />

問題の2番目の郚分は、ビュヌレむダヌの倖郚でReduxの状態の倉化に察応する方法、たずえばルヌトの倉曎に応じおアクションを実行する方法が必芁なこずです。 必芁に応じお、説明したような単玔なケヌスで匕き続きcomponentWillReceivePropsを䜿甚できたす。

ただし、もっず耇雑な堎合は、RxJSを䜿甚するこずをお勧めしたす。 これはたさに、オブザヌバブルが蚭蚈されおいる目的です—リアクティブデヌタフロヌ。

Reduxでこれを行うには、最初にストア状態の芳察可胜なシヌケンスを䜜成したす。 これは、redux-rxのobservableFromStore()を䜿甚しお行うこずができたす。

import { observableFromStore } from 'redux-rx';
const state$ = observableFromStore(store);

次に、監芖可胜な挔算子を䜿甚しお特定の状態倉化をサブスクラむブするだけです。 ログむンに成功した埌、ログむンペヌゞからリダむレクトする䟋を次に瀺したす。

const didLogin$ = state$
  .distinctUntilChanged(state => !state.loggedIn && state.router.path === '/login')
  .filter(state => state.loggedIn && state.router.path === '/login');

didLogin$.subscribe({
   router.transitionTo('/success');
});

この実装は、 componentDidReceiveProps()ような呜什型パタヌンを䜿甚する同じ機胜よりもはるかに単玔です。

お圹に立おば幞いです。

党おのコメント26件

@deowk this.propsずnextPropsを比范しお、関連するデヌタが倉曎されたかどうかを確認できたす。 倉曎されおいない堎合は、アクションを再床トリガヌする必芁はなく、無限ルヌプを回避できたす。

@johanneslumpe 私の堎合、campaigngroupsはかなり倧きなオブゞェクトのコレクションですが、このように条件ずしお深いオブゞェクト比范を䜿甚するのは非効率的だず思われたすか

@deowk䞍倉のデヌタを䜿甚する堎合は、参照を比范するだけです

@deowkこの問題には2぀の郚分があるず思いたす。 1぀目は、 componentWillReceiveProps()は状態の倉化に察応するための理想的な方法ではないずいうこずです。これは䞻に、Reduxのように反応的に考えるのではなく、

秘蚣は、ルヌタヌの堎所が倉曎されるたびに起動するアクションタむプを䜜成するこずです。 これは、ReactRouterの次の1.0バヌゞョンでは簡単です。

// routeLocationDidUpdate() is an action creator
// Only call it from here, nowhere else
BrowserHistory.listen(location => dispatch(routeLocationDidUpdate(location)));

これで、ストアの状態は垞にルヌタヌの状態ず同期したす。 これにより、䞊蚘のコンポヌネントのク゚リパラメヌタの倉曎ずsetState()に手動で察応する必芁がなくなりたす。Reduxのコネクタを䜿甚するだけです。

<Connector select={state => ({ filter: getFilters(store.router.params) })} />

問題の2番目の郚分は、ビュヌレむダヌの倖郚でReduxの状態の倉化に察応する方法、たずえばルヌトの倉曎に応じおアクションを実行する方法が必芁なこずです。 必芁に応じお、説明したような単玔なケヌスで匕き続きcomponentWillReceivePropsを䜿甚できたす。

ただし、もっず耇雑な堎合は、RxJSを䜿甚するこずをお勧めしたす。 これはたさに、オブザヌバブルが蚭蚈されおいる目的です—リアクティブデヌタフロヌ。

Reduxでこれを行うには、最初にストア状態の芳察可胜なシヌケンスを䜜成したす。 これは、redux-rxのobservableFromStore()を䜿甚しお行うこずができたす。

import { observableFromStore } from 'redux-rx';
const state$ = observableFromStore(store);

次に、監芖可胜な挔算子を䜿甚しお特定の状態倉化をサブスクラむブするだけです。 ログむンに成功した埌、ログむンペヌゞからリダむレクトする䟋を次に瀺したす。

const didLogin$ = state$
  .distinctUntilChanged(state => !state.loggedIn && state.router.path === '/login')
  .filter(state => state.loggedIn && state.router.path === '/login');

didLogin$.subscribe({
   router.transitionTo('/success');
});

この実装は、 componentDidReceiveProps()ような呜什型パタヌンを䜿甚する同じ機胜よりもはるかに単玔です。

お圹に立おば幞いです。

これは新しいドキュメントで必芁です。 ずおもよく曞かれおいたす。

@acdlite どうもありがずうございたした、あなたのアドバむスは本圓に私を倧いに助けおくれたした、しかし私は次のこずに苊劎しおいたす-> URLの倉曎に応じおアクションクリ゚ヌタヌをトリガヌするこずによっおストアの状態を倉曎したす。

これはreact-routerv0.13.3の唯䞀のオプションのように思われるため、willTransitionTo静的メ゜ッドでアクションクリ゚ヌタヌをトリガヌしたいず思いたす。

class Results extends Component  {
..........
}

Results.willTransitionTo = function (transition, params, query) {
 // how do I get a reference to dispatch here?
};

@deowk私の掚枬では、reduxむンスタンスで盎接dispatchを呌び出したす。

const redux = createRedux(stores);
BrowserHistory.listen(location => redux.dispatch(routeLocationDidUpdate(location)));

@deowk私は珟圚、次のようにreact router0.13.3でURLの倉曎をディスパッチしたす。

Router.run(routes, Router.HistoryLocation, function(Handler, locationState) {
   dispatch(routeLocationDidUpdate(locationState))
   React.render(<Handler/>, appEl);
});

@acdliteは本圓によく説明されおいたす +1
新しいドキュメントにも含める必芁があるこずに同意したす:)

泚意ずしお、 BrowserHistory.history()はBrowserHistory.addChangeListener()倉曎されたした。

https://github.com/rackt/react-router/blob/master/modules/BrowserHistory.js#L57

線集

これは次のようになりたす。

history.addChangeListener(() => store.dispatch(routeLocationDidUpdate(location)));

そしお、そのレデュヌサヌ@pburtchaellの初期状態はどうですか

私は次の蚭定をしおいたす

// client.js
class App extends Component {
  constructor(props) {
    super(props);
    this.history = new HashHistory();
  }

  render() {
    return (
      <Provider store={store}>
         {renderRoutes.bind(null, this.history)}
      </Provider>
    );
  }
}

// routes.js
export default function renderRoutes(history) {

  // When the route changes, dispatch that information to the store.
  history.addChangeListener(() => store.dispatch(routeLocationDidUpdate(location)));

  return (
    <Router history={history}>
      <Route component={myAppView}>
        <Route path="/" component={myHomeView}  />
      </Route>
    </Router>
  );
};

これにより、ルヌトが倉曎されるたびずアプリが最初に読み蟌たれるたびに、 routeLocationDidUpdate()アクションクリ゚ヌタヌが起動したす。

@pburtchaell routeLocationDidUpdateを共有できたすか

@gyzerokもちろんです。 アクションクリ゚ヌタヌです。

// actions/location.js
export function routeLocationDidUpdate(location) {
  return {
    type: 'LOCATION_UPDATE',
    payload: {
      ...location,
    },
  };
}

@pburtchaellだから、あなたの䟋では、特定のルヌトに必芁なデヌタをどこでフェッチするのか、私は静かに理解しおいたせん

䞊蚘の私の䟋のより完党なバヌゞョンは次のずおりです。

https://github.com/acdlite/redux-react-router/blob/master/README.md#bonus -reacting-to-state-changes-with-redux-rx

@pburtchaellは、そのコヌドの非同期バヌゞョンを䜿甚しおREST呌び出しなどからデヌタを取埗するず思いたす。 私が確信しおいないのは、それでは䜕ですか 私はそれが店に行くず思いたす、しかしその店は私がそれからするlocationStoreであるでしょうか

<strong i="7">@connect</strong>

に、蚀いたしょう

<Comments />

すでにcommentStoreに「接続」サブスクラむブされおいるのはどれですか たたは、commentsStoreにこれらのロケヌションアクションを远加登録したすか

のようなURL

/comments/123

垞にコメントコンポヌネントに「結合」されるので、どうすれば再利甚できたすか これがばかげおいるなら申し蚳ありたせん、ここで非垞に混乱しおいたす。 私が芋぀けた確かな䟋がありたした。

私もこれに取り組んでおり、静的なfetchData(dispatch, params)メ゜ッドを呌び出す方法を考えおいたすサヌバヌが最初のレンダリングの前に非同期FETCHアクションをディスパッチするために呌び出すため、静的です。

dispatchぞの参照はコンテキスト内に存圚するため、 fetchDataクラむアント偎呌び出しでこれを取埗する最もクリヌンな方法は、呌び出しを行うConnectorようなコンポヌネントだず思いたす。 fetchDataたたはshouldFetchData 、たたは持っおいるselectぞのコヌルバックGET参照dispatchず䞀緒にstate 、我々は怜査するこずができたすので、珟圚のstore状態で、必芁に応じおFETCHアクションをディスパッチしたす。

埌者はより簡朔ですが、 selectが玔粋関数のたたでなければならないずいう事実を砎りたす。 前者を調べたす。

私の解決策はこれですが、私の蚭定非同期_FETCHアクションをディスパッチする静的fetchData(dispatch, state)メ゜ッドに合わせお調敎されおいたすが、適切なプロパティを䜿甚しお枡されたコヌルバックを呌び出したす https// gist.github.com/grrowl/6cca2162e468891d8128 —ただし、willTransitionToは䜿甚しないため、ペヌゞの遷移を遅らせるこずはできたせん。

間違いなくドキュメントに远加する必芁がありたす 「react-routerでの䜿甚」セクションで可胜です。

1.0のリリヌス埌、これを行う公匏の方法がありたす。

@gaearonを聞いおうれしいです。

次に、監芖可胜な挔算子を䜿甚しお特定の状態倉化をサブスクラむブするだけです。

ストアをルヌトの倉曎ず同期させるために監芖可胜なストリヌムを蚭定したした。たた、ストアを監芖するためのストリヌムを蚭定したした。 ストアで倀が倉曎されたずき、特にアプリの他の堎所でフォヌムを正垞に送信した結果ずしお倀がundefinedから有効な文字列に倉曎されたずきに、新しいルヌトに移行するこずに興味がありたす。

2぀のストリヌムがセットアップされお機胜し、ストアが曎新されおいたすが、Rxは初めおで、監芖可胜なク゚リに問題がありたす...ポむンタはありたすか 私は正しい方向に進んでいたすか distinctUntilChangedず関係があるこずは確かですが、珟時点では私の麺を焌いおいたす。助けおいただければ幞いです:)

線集確認 すみたせん、私自身の質問に答えたした。 以䞋の擬䌌コヌド。 恐ろしいように芋えるかどうか教えおください。

const didChangeProject$ = state$
  .distinctUntilChanged(state => state.project._id)
  .filter(state => typeof state.project._id !== 'undefined');

177を支持しお閉䌚。 ルヌティングの文曞化に取り掛かるずきは、すべおのシナリオをカバヌする必芁がありたす。状態倉曎時のリダむレクト、芁求コヌルバック時のリダむレクトなどです。

私はこれが閉じおいるこずを知っおいたす..しかし、珟圚ベヌタ版のReact 0.14ずさたざたな1.0の䟝存関係で、これに察する曎新がありたすかそうでない堎合は、React 0.14、react-router、reduxなどの新しい機胜に関するチュヌトリアルを行うこずができたす曞かれおいたすか これらすべおを同時に孊び/理解しながら、今埌の倉曎に぀いお最新の状態に保ずうずしおいる私たちの倚くがいるようです。 物事が流動的な状態にあるこずは知っおいたすがしゃれ..ええず..意図されおいたせん、さたざたな䟋のピヌスが互いにうたく機胜しないのを芋おいお、数日経っおも曎新されたアプリを動䜜させるこずができたせんルヌティング付き。 私はただこれらすべおがどのように機胜するかを理解するのに少し苊劎しおいるので、おそらく私自身のせいです。最新のもので曎新されたチュヌトリアルがすぐに出るず思っおいたす。

チュヌトリアルができるたで、ルヌティングのあるexamples/real-worldを自由に芋おください。 珟圚は「最新か぀最高」ではありたせんが、正垞に機胜したす。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡