Используйте гидрат () с асинхронным. компоненты
Приложение, над которым я работаю, основано на React Fiber и React Router V3.
Пытаясь использовать hydrate()
вместо render()
с асинхронными компонентами я столкнулся со следующей проблемой: HTML, возвращаемый из SSR, отличается от клиентского.
В результате React перемонтирует весь DOM и выдает следующее предупреждение: Did not expect server HTML to contain...
,
React Training также не предоставляет решения: разделение кода + рендеринг сервера
Есть ли решение для достижения этой цели?
Обновления:
Простой пример
(псевдокод)
App.js:
export default () => <div>Lorem Ipsum</div>;
client.js:
const createRoutes = store => ({
path: '/',
getComponent(nextState, cb) {
require('./App'); // some async require
},
onEnter: (nextState, replace, cb) => {
store.dispatch(fetchData())
.then(() => cb())
.catch(cb);
}
});
match({history, routes: createRoutes(store)},
(error, redirectLocation, renderProps) => {
hydrate(
<Router history={history} routes={createRoutes(store)} />,
document.getElementById('app')
);
});
server.js
match({routes: createRoutes(store), location: req.url},
(err, redirectLocation, renderProps) => {
const content = renderToString(<RouterContext {...renderProps}/>);
// send content to client
});
1 ответ
Я изучил проблему немного глубже и нашел решение. Для достижения гидратации DOM необходимо учитывать следующее:
Я пример выше в
client.js
Я призвалcreateRoutes(store)
дважды. Это избыточно, потому чтоrenderProps
уже имеетroutes
собственность подготовлена для<Route />
составная часть. Из-за этой ошибкиonEnter
был вызван дважды, поэтому выборка данных была также выполнена дважды.Чтобы избежать несоответствия HTML при выборке данных на стороне сервера и клиента
onEnter
не должен вызываться при первом рендере на стороне клиента.match
функция ждетgetComponent
обратный вызов выполняется до рендера. Таким образом, основной вопрос не так, потому что эта функциональность доступна из коробки.