redux-observable を react-router で使用する場合、ルート変更中に react-router の onEnter フック内のドキュメントの指示に従って、新しいエピックを非同期に追加することは理にかなっていますか?
./epics/index.js
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { combineEpics } from 'redux-observable';
import { epic1 } from './epic1'
import { epic2 } from './epic2'
export const epic$ = new BehaviorSubject(combineEpics(epic1, epic2));
export const rootEpic = (action$, store) =>
epic$.mergeMap(epic =>
epic(action$, store)
);
export {
rootEpic
};
...ルート/SomePath/index.js
import { epic$ } from './../../../../epics/index'
import { epic3 } from './../../../../epics/epic3'
module.exports = {
path: 'some-path',
getComponent( location, cb ) {
require.ensure( [], ( require ) => {
cb( null, require( './components/SomePath' ) )
} )
},
onEnter() {
epic$.next(epic3)
}
}
Rxjs と redux-observable の非常に新しい。1. この場合、 /some-path に移動するたびに epic3 が rootEpic に再度追加されるのでしょうか? 2. rootEpic に追加されたエピックを console.log に記録したい場合、どうすればよいですか?
@JayPhelpsに応じて編集
いくつかの点について説明を求めてもよろしいですか?
registerEpic fn はうまく機能します。私は .distinct() 演算子を使用して、重複した叙事詩の登録の問題に次のように対処していました。
export const epic$ = new BehaviorSubject(combineEpics(epic1, epic2)).distinct()
これは、怠惰な叙事詩の登録を処理する同様に有効/適切な方法ですか?そうでない場合は、その理由を説明していただけますか?
- 私はrequire.ensureとES6インポートを備えたcreate-react-appを使用しています(これらはインポートの異なる方法ですよね?)、基本的に、コードを含むreact-routerのヒュージアプリの例
require.ensure
をコピーして貼り付けましたが、どこでもそれ以外の場合は、ファイルの先頭で import ステートメントを使用しています。
したがって、エピックと registerEpic fn を上部にインポートすると機能するように見えますが、require.ensure の最初の引数内にパスを配置することも機能するようです。require.ensure AND import ステートメントを使用すると、混乱しますか? ルートが必要とするすべてのものをロードするために require.ensure を使用する場合、そのルートのコンポーネントのネストされた (ルートのない) コンポーネント内のすべての import ステートメントを削除することを意味しますか?
import { epic3 } from './../../epics/epic3'
import { epic4 } from './../../epics/epic4'
import { registerEpic } from './../../epics/index'
module.exports = {
path: 'my-path',
getComponent( location, done ) {
require.ensure( [], ( require ) => {
registerEpic(addYoutubeEpic)
registerEpic(linkYourSiteEpic)
done( null, require( './components/Edit' ) )
} )
}
}
非同期ロード用の 'getComponent' fn でのエピックの登録について - エピックが登録されるまでルートのコンポーネントがレンダリングされないように、ここで同期ロードを行うことが実際には望ましいと思いました。ユーザーがエピックの登録が必要な詳細情報の取得やフォームの送信など、エピックがまだ登録されていないルートで何かを行おうとするとどうなりますか?
エピックを遅延登録するのに適切な、react-router module.export 宣言以外の場所はありますか? 私のプロジェクトの多くのルートはログインを必要としないため、ログインしても常にルートの変更がトリガーされるとは限りません。ただし、ユーザーがログインした後に登録する必要があるエピックがたくさんあります。現在、authReducer でトークン変数を設定することで、本当にばかげた、おそらく間違った方法でそれを行っていますが、関数を呼び出すだけです。新しい叙事詩を登録します。
'./../reducers/authReducer.js' import { greatEpic } from './../epics/fetchFollowListEpic' import { usefulEpic } from './../epics/fetchMyCollectionsEpic' // and a few more import { registerEpic } from './../epics/index' const addEpics = () => { registerEpic(greatEpic) registerEpic(usefulEpic) ...etc } export default function reducer( state = { loggingIn: false, loggedIn: false, error: '', }, action ) { switch ( action.type ) { case "LOGIN_SEQUENCE_DONE": { return { ...state, aid: setAuthToken(action.payload), loginFailed: false, addEpics: addEpics(), } }
レデューサーではなく、loginEpic がエピックを登録するのに適した場所になると思います。(あなたのログイン例を github で見つけたので、見覚えがあるかもしれません)。それは正しいですか、それとも私は完全にベースから外れていますか? 私は .concat() が同期であることを知っており、redux が同期であることを知っています。それとも、問題にならないほど急速に物事が進んでいるということですか? それとも、インポートステートメントと、さらに調査する必要があるコード分割をwebpackがどのように処理するかについて、私が持っているいくつかの本質的な誤解のためにのみ機能しますか?
./../epics/loginEpic
export const loginEpic = action$ =>
action$.ofType("LOGIN")
.mergeMap(action =>
Observable.fromPromise(axios.post('webapi/login', action.payload))
.flatMap(payload =>
// Concat multiple observables so they fire sequentially
Observable.concat(
// after LOGIN_FULILLED
Observable.of({ type: "LOGIN_FULFILLED", payload: payload.data.aid }),
// ****This is where I think I should be registering the epics right after logging in. "ANOTHER_ACTION" below depends upon one of these epics****
Observable.of({type: "ANOTHER_ACTION", payload: 'webapi/following'}),
Observable.of({type: "LOGIN_SEQUENCE_DONE"}),
)
)
.startWith({ type: "LOGIN_PENDING" })
.takeUntil(action$.ofType("LOGIN_CANCELLED"))
.catch(error => Observable.of({
type: "LOGIN_REJECTED",
payload: error,
error: true
}))
);