После того, как я все больше и больше узнаю о реакции, я чувствую себя довольно уверенно, у меня есть решение.
Я передаю объект browserContext
по всем отображаемым маршрутам, очень похоже на staticContext
на сервере.В browserContext
я установил два значения;isFirstRender
и usingDevServer
.isFirstRender
имеет значение true только тогда, когда приложение отображается в первый раз, а usingDevServer
- только true при использовании webpack-dev-server.
const store = createStore (redurs, initialReduxState, middleware);
Файл ввода для стороны браузера:
const browserContext = {
isFirstRender: true,
usingDevServer: !!process.env.USING_DEV_SERVER
};
const BrowserApp = () => {
return (
<Provider store={store}>
<BrowserRouter>
{renderRoutes(routes, { store, browserContext })}
</BrowserRouter>
</Provider>
);
};
hydrate(
<BrowserApp />,
document.getElementById('root')
);
browserContext.isFirstRender = false;
USING_DEV_SERVER
определен в файле конфигурации веб-пакета с использованием webpack.DefinePlugin
Затем я написал компонент HOC, который используетэта информация для извлечения исходных данных только в ситуациях, когда это необходимо:
function wrapInitialDataComponent(Component) {
class InitialDatacomponent extends React.Component {
componentDidMount() {
const { store, browserContext, match } = this.props;
const fetchRequired = browserContext.usingDevServer || !browserContext.isFirstRender;
if (fetchRequired && Component.fetchInitialData) {
Component.fetchInitialData(store.dispatch, match);
}
}
render() {
return <Component {...this.props} />;
}
}
// Copy any static methods.
hoistNonReactStatics(InitialDatacomponent, Component);
// Set display name for debugging.
InitialDatacomponent.displayName = `InitialDatacomponent(${getDisplayName(Component)})`;
return InitialDatacomponent;
}
И затем последнее, что нужно сделать, - это обернуть все компоненты, отрисованные с помощью router, с этим компонентом HOC.Я сделал это, просто рекурсивно перебирая маршруты:
function wrapRoutes(routes) {
routes.forEach((route) => {
route.component = wrapInitialDataComponent(route.component);
if (route.routes) {
wrapRoutes(route.routes);
}
});
}
const routes = [ ... ];
wrapRoutes(routes);
И это, похоже, делает свое дело:)