[英]Async server-side rendering using redux & react
I am having serious difficulty getting a working server-side rendering solution using React
, Redux
, Redux-Thunk
and React-Router
.我在使用
React
、 Redux
、 Redux-Thunk
和React-Router
获得有效的服务器端渲染解决方案时遇到了严重的困难。
At the moment, my solution works on the client-side following the basic guidelines and this post: https://codepen.io/stowball/post/a-dummy-s-guide-to-redux-and-thunk-in-react .目前,我的解决方案在客户端遵循基本准则和这篇文章: https : //codepen.io/stowball/post/a-dummy-s-guide-to-redux-and-thunk-in-反应。 For the scope of simplicity, I will be using the code from that blog as my example.
为简单起见,我将使用该博客中的代码作为示例。 The only alteration is that I have added a
console.log("X");
唯一的改变是我添加了一个
console.log("X");
to the reducer function items
so that I know when it is called.到减速器功能
items
以便我知道何时调用它。 The resultant function is:结果函数是:
export function items(state = [], action) {
switch (action.type) {
case 'ITEMS_FETCH_DATA_SUCCESS':
console.log('X');
return action.items;
default:
return state;
}
}
and I also set the itemsFetchData
function to return the promise, becoming:我还设置了
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)));
};
}
As I need server-side rendering.因为我需要服务器端渲染。 I setup Express to consume my middleware
handleRender
which in turn calls renderFullPage
that returns the HTML string.我设置 Express 来使用我的中间件
handleRender
,它反过来调用返回 HTML 字符串的renderFullPage
。 The Express implementation can be assumed correct.可以假定 Express 实现是正确的。 My
handleRender
looks like the below我的
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));
});
}
Using the above code, Y
is printed to the console, but X
is never printed, meaning the reducer function is not being called.使用上面的代码,
Y
被打印到控制台,但X
永远不会被打印,这意味着没有调用 reducer 函数。 If I remove the then
from the promise in my handleRender, thus becoming:如果我从我的 handleRender 中的承诺中删除
then
,从而变成:
dispatch(itemsFetchData(''http://5826ed963900d612000138bd.mockapi.io/items''));
console.log("Y");
// ... remaining code remains unaltered
The reducer function is being called correctly and the Redux store updated correctly, however since this is asynchronous the handleRender
would have returned the HTML already. reducer 函数被正确调用并且 Redux 存储正确更新,但是由于这是异步的,
handleRender
将已经返回 HTML。
Any help would be greatly appreciated.任何帮助将不胜感激。 It's been a long day.
这是漫长的一天。
The source of the confusion was caused because the reducer was injected after the itemsFetchData
was called.造成混乱的根源是因为在调用
itemsFetchData
之后注入了itemsFetchData
。 The problem was only noted when using then
because without it, the component Main
which injected the reducer was still included and everything seemed normal.使用时,问题只是指出
then
,因为没有它,成分Main
其注入减速仍包括在内,似乎一切正常。 When it was relying on the then
I ended up with the then
unable to dispatch because there was no reducer and the Main
component not included because it was waiting for the dispatch.当它依托
then
我结束了与then
无法调度,因为没有减速和Main
部件不包括在内,因为它在等待调度。
To solve the problem, I have included the reducer in my combineReducers
.为了解决这个问题,我在我的
combineReducers
包含了 reducer。
Like I said, it was a long day.就像我说的,这是漫长的一天。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.