我有一个用打字稿中的 razzle 制作的服务器端渲染反应应用程序。这就是我想要实现的。我希望服务器在呈现我的应用程序中的任何页面之前获取经过身份验证的数据,将其发送到商店,然后将其插入呈现的文档中,以便客户端在商店中提取和使用。
我已经可以使用react-router-config和promise对特定路由执行调度操作,并且每个请求都是通过 axios 发出的。
我的商店
import { createStore, applyMiddleware, compose } from "redux";
import promiseMiddleware from "redux-promise-middleware";
import { composeWithDevTools } from "redux-devtools-extension";
import thunkMiddleware from "redux-thunk";
import reducer, { IRootState } from "./root.reducer";
import notificationMiddleware from "config/notification-middleware";
import loggerMiddleware from "config/logger-middleware";
import loadingBarMiddleware from "config/loading-bar-middleware";
const defaultMiddlewares = [
thunkMiddleware,
notificationMiddleware,
promiseMiddleware,
loadingBarMiddleware,
loggerMiddleware,
];
const composedMiddlewares = (middlewares: any) =>
process.env.NODE_ENV === "development"
? composeWithDevTools(
applyMiddleware(...defaultMiddlewares, ...middlewares)
)
: compose(applyMiddleware(...defaultMiddlewares, ...middlewares));
const initialize = (initialState?: IRootState, middlewares = []) => createStore(reducer, initialState, composedMiddlewares(middlewares));
export default initialize;
getSession 的动作
export const getSession: any = () => async (dispatch: any) => {
await dispatch({
type: ACTION_TYPES.GET_SESSION,
payload: axios.get("api/account")
})
};
服务器.ts
import renderApp from "server/renderer";
const Routes = [
{
path: "/",
component: Home,
loadData: (dispatch: ThunkDispatch<IRootState, void, Action<any>>) => dispatch(getSession()),
},
// etc.
];
// Create a new Redux store instance
const store = initStore();
const { dispatch } = store;
const actions = bindActionCreators({ clearAuthentication }, dispatch);
setupAxiosInterceptors(() => actions.clearAuthentication("Unauthorized action"), Cookies.load("jhi-authenticationToken", req));
const routes = matchRoutes(Routes, req.path);
const promises = routes.map(({ route }: any) =>
route.loadData instanceof Function ? route.loadData(dispatch) : Promise.resolve()
);
Promise.all(promises).then(() => {
renderApp(store, req, res);
});
renderer.tsx // 从我们的 Redux 存储中获取初始状态
import serialize from "serialize-javascript";
const finalState = store.getState();
const markup = renderToString(
<StaticRouter context={context} location={req.url}>
<Provider store={store}>
<App />
</Provider>
</StaticRouter>
)
);
res.status(200).send(`<!DOCTYPE html>
<html lang="fr">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="utf-8" />
</head>
<body>
<div id="root">${markup}</div>
<script>
window.__PRELOADED_STATE__ = ${serialize(finalState)};
</script>
</body>
</html>`
)
);
}
};
但是我的商店没有更新,并且我仍然拥有与初始状态相同的数据。
笔记
- 我检查了浏览器呈现的 HTML,这是我收到的初始状态
- 似乎这些操作并没有更新我的状态,因为我在减速器中插入了一些 console.logs 并且终端上没有出现日志
- getSession在客户端上运行良好。