Gaj*_*jus 1 javascript redux-saga react-redux
我正在使用redux-saga实现服务器端渲染。
我正在遵循redux-saga存储库中提供的“真实世界”示例。
renderToString呈现应用程序。componentWillMount,从而调度动作GET_GEOLOCATION和GET_DATE。这些异步操作将使用SET_GEOLOCATION和解决SET_DATE。renderToString完成渲染应用程序;END动作终止了传奇听众问题是,SET_GEOLOCATION和SET_DATE自己来put一个新的动作GET_MOVIES。但是,在调用SET_GEOLOCATION和时SET_DATE,传奇侦听器不再处于活动状态(我们在之后终止了它renderToString)。因此,尽管GET_MOVIES将被分派,但GET_MOVIES动作不会被选择并且SET_MOVIE永远不会发生。
服务器代码:
app.get('*', (req, res) => {
const history = createMemoryHistory({
initialEntries: [
req.url
]
});
const store = configureStore(undefined, history);
const context = {};
const rootComponent = <Provider store={store}>
<StaticRouter context={context} location={req.url}>
<Route component={RootRoute} />
</StaticRouter>
</Provider>;
store
.runSaga(rootSaga).done
.then(() => {
const body = renderToString(rootComponent);
const response = renderHtml(body, store);
res
.send(response);
})
.catch((error) => {
res
.status(500)
.send(error.message);
});
// Force componentWillMount to issue saga effects.
renderToString(rootComponent);
store.close();
});
Run Code Online (Sandbox Code Playgroud)
萨加斯:
const watchNewSearchCriteria = function *(): Generator<*, *, *> {
yield takeLatest([
SET_GEOLOCATION,
SET_DATE
], function *() {
const {
coordinates,
date
} = yield select((state) => {
return {
coordinates: state.movieEventsView.location ? state.movieEventsView.location.coordinates : null,
date: state.movieEventsView.date
};
});
if (!coordinates || !date) {
return;
}
yield put(getMovies({
coordinates,
date
}));
});
};
const watchGetMovies = function *() {
yield takeLatest(GET_MOVIES, function *(action) {
const result = yield call(getMovies, action.payload);
yield put(setMovies(result));
});
};
Run Code Online (Sandbox Code Playgroud)
如何延迟store.close到没有除状态以外的sagas之后take?
如何延迟
store.close到没有除状态以外的sagas之后take?
要回答我自己的问题,我需要观察所有解决方案put。我可以使用Saga Monitor来做到这一点。
可以在创建redux-saga中间件时配置Saga Monitor 。对于我们的用例,它需要跟踪每一个动作put,并在解决/拒绝/取消动作时将其从索引中删除。
const activeEffectIds = [];
const watchEffectEnd = (effectId) => {
const effectIndex = activeEffectIds.indexOf(effectId);
if (effectIndex !== -1) {
activeEffectIds.splice(effectIndex, 1);
}
};
const sagaMiddleware = createSagaMiddleware({
sagaMonitor: {
effectCancelled: watchEffectEnd,
effectRejected: watchEffectEnd,
effectResolved: watchEffectEnd,
effectTriggered: (event) => {
if (event.effect.CALL) {
activeEffectIds.push(event.effectId);
}
}
}
});
Run Code Online (Sandbox Code Playgroud)
我们需要从商店的使用者那里访问它,因此我将其分配activeEffectIds给商店实例:
store.runSaga = sagaMiddleware.run;
store.close = () => {
store.dispatch(END);
};
store.activeEffectIds = activeEffectIds;
Run Code Online (Sandbox Code Playgroud)
然后,而不是同步停止传奇...
renderToString(rootComponent);
store.close();
Run Code Online (Sandbox Code Playgroud)
我们需要延迟store.close到store.activeEffectIds.length0。
const realDone = () => {
setImmediate(() => {
if (store.activeEffectIds.length) {
realDone();
} else {
store.close();
}
});
};
// Force componentWillMount to issue saga effects.
renderToString(rootComponent);
realDone();
Run Code Online (Sandbox Code Playgroud)
store.close仅在解决所有异步影响时才调用Now 。
| 归档时间: |
|
| 查看次数: |
944 次 |
| 最近记录: |