使用React
,Redux
,Redux-Thunk
和React-Router
获取正常工作的服务器端渲染解决方案时遇到了严重困难。
目前,我的解决方案在客户端遵循基本准则和帖子:https://codepen.io/stowball/post/a-dummy-s-guide-to-redux-and-thunk-in-react。为了简单起见,我将使用该博客中的代码作为我的示例。唯一的变化是我在减速器函数console.log("X");
中添加了items
,以便我知道它何时被调用。结果函数是:
export function items(state = [], action) {
switch (action.type) {
case 'ITEMS_FETCH_DATA_SUCCESS':
console.log('X');
return action.items;
default:
return state;
}
}
我还设置itemsFetchData
函数以返回承诺,成为:
export function itemsFetchData(url) {
return (dispatch) => {
dispatch(itemsIsLoading(true));
return fetch(url)
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
dispatch(itemsIsLoading(false));
return response;
})
.then((response) => response.json())
.then((items) => dispatch(itemsFetchDataSuccess(items)))
.catch(() => dispatch(itemsHasErrored(true)));
};
}
因为我需要服务器端渲染。我设置Express以使用我的中间件handleRender
,后者又调用返回HTML字符串的renderFullPage
。可以假设Express实现是正确的。我的handleRender
如下所示
export function handleRender(req, res) {
// Create a new Redux store instance
const store = configureStore();
const { dispatch } = store;
dispatch(itemsFetchData(''http://5826ed963900d612000138bd.mockapi.io/items'')).then(() => {
console.log("Y");
// Render the component to a string
const html = renderToString(
<Provider store={store}>
<div id="app">
<StaticRouter context={{}} location={req.url}>
<Main />
</StaticRouter>
</div>
</Provider>
);
// Grab the initial state from our Redux store
const preloadedState = store.getState();
// Send the rendered page back to the client
res.send(renderFullPage(html, preloadedState));
});
}
使用上面的代码,Y
将打印到控制台,但永远不会打印X
,这意味着不会调用reducer函数。如果我从handleRender中的promise中删除then
,从而成为:
dispatch(itemsFetchData(''http://5826ed963900d612000138bd.mockapi.io/items''));
console.log("Y");
// ... remaining code remains unaltered
正确调用reducer函数并正确更新Redux存储,但由于这是异步的,因此handleRender
已经返回了HTML。
非常感谢任何帮助。这是漫长的一天。
答案 0 :(得分:1)
引起混淆的原因是因为在调用itemsFetchData
之后注入了reducer。只有在使用then
时才会发现问题,因为没有它,注入reducer的组件Main
仍然包含在内,一切似乎正常。当它依赖于then
我最终导致then
无法发送,因为没有减速器且Main
组件未包括在内,因为它正在等待发送。
要解决这个问题,我已将减速器包含在我的combineReducers
。
就像我说的那样,这是漫长的一天。