我正在创建一个 React SSR 项目。我已经集成了 Redux 实现了服务器端渲染。但是,当我使用带有批量数据的 api 浏览某个组件时,在加载时,点击浏览器的后退按钮,我的路线会立即更改,该组件的数据已加载,但在当前组件获取其数据之前不会显示,并且渲染它。
那么有什么方法可以在 url 更改时停止异步节点服务器端调用数据,即使该异步数据尚未到来?我现在正在使用axios。
这是我的服务器渲染:
export default function serverRenderer({ clientStats, serverStats }) {
return (req, res, next) => {
const context = {};
const pageContainer = req.pageContainer || {};
const PAGE = pageContainers.default[pageContainer];
if (!PAGE || typeof (PAGE.fetchData) !== 'function') {
const markup = ReactDOMServer.renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
<RouteComp />
</StaticRouter>
</Provider>,
);
const helmet = Helmet.renderStatic();
return res.status(200).send(Template({
markup,
helmet,
state: store.getState(),
}));
}
return PAGE.fetchData(store, req.urlparams).then(() => {
const markup = ReactDOMServer.renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
<RouteComp />
</StaticRouter>
</Provider>,
);
const helmet = Helmet.renderStatic();
res.status(200).send(Template({
markup,
helmet,
state: store.getState(),
}));
}).catch((e) => {
console.log('fetch data error:::', e);
});
};
}
这是client.js
// Grab the state from a global variable injected into the server-generated HTML
const preloadedState = window.__PRELOADED_STATE__;
// Allow the passed state to be garbage-collected
delete window.__PRELOADED_STATE__;
// Create Redux store with initial state
const store = createStore(reducer, preloadedState, applyMiddleware(thunk));
hydrate(
<Provider store={store}>
<BrowserRouter>
<RouteComp />
</BrowserRouter>
</Provider>,
document.getElementById('app'),
);
这是一个容器,它具有获取数据的静态方法。服务端调用匹配Container的fetchData
class HomeContainer extends Component {
static fetchData(store) {
const promises = [
store.dispatch(fetchHomePageStarted()),
getHomePageData()
.then((response) => {
const { data } = response;
return store.dispatch(fetchHomePageSuccess(data));
})
.catch((error) => {
console.log('error occurred -> ', error);
return store.dispatch(fetchHomePageFailed(error));
}),
];
return Promise.all(promises);
}
}