Загрузка данных компонента асинхронно на стороне сервера с Mobx
У меня возникла проблема с выяснением того, как компонент реагирования должен иметь начальное состояние, основанное на асинхронно полученных данных.
MyComponent извлекает данные из API и устанавливает его внутренний data
собственность через Mobx action
,
Сторона клиента, componentDidMount
вызывается и данные извлекаются, затем устанавливаются и корректно отображаются.
import React from 'react';
import { observer } from 'mobx-react';
import { observable, runInAction } from 'mobx';
@observer
export default class MyComponent extends React.Component {
@observable data = [];
async fetchData () {
loadData()
.then(results => {
runInAction( () => {
this.data = results;
});
});
}
componentDidMount () {
this.fetchData();
}
render () {
// Render this.data
}
}
Я понимаю, что на сервере, componentDidMount
не называется.
У меня есть что-то вроде этого для моего сервера:
import React from 'react';
import { renderToString } from 'react-dom/server';
import { useStaticRendering } from 'mobx-react';
import { match, RouterContext } from 'react-router';
import { renderStatic } from 'glamor/server'
import routes from './shared/routes';
useStaticRendering(true);
app.get('*', (req, res) => {
match({ routes: routes, location: req.url }, (err, redirect, props) => {
if (err) {
console.log('Error', err);
res.status(500).send(err);
}
else if (redirect) {
res.redirect(302, redirect.pathname + redirect.search);
}
else if (props) {
const { html, css, ids } = renderStatic(() => renderToString(<RouterContext { ...props }/>));
res.render('../build/index', {
html,
css
});
}
else {
res.status(404).send('Not found');
}
})
})
Я видел много постов, где исходный магазин вычисляется и проходит через Provider
составная часть. Мои компоненты отображаются, но их состояние не инициализировано. Я не хочу сохранять эти данные в хранилище и хочу, чтобы они были локально доступны компоненту. Как это можно сделать?
1 ответ
Для рендеринга на стороне сервера сначала необходимо получить данные, а затем выполнить рендеринг. Компоненты не имеют жизненного цикла во время SSR, просто визуализируются в строку один раз, но не могут реагировать на любые будущие изменения.
Поскольку ваш метод datafetch является асинхронным, это означает, что он никогда не сможет повлиять на вывод, поскольку компонент уже будет записан. Таким образом, ответ - сначала получить данные, а затем смонтировать и визуализировать компоненты без использования какого-либо асинхронного механизма (обещания, асинхронизация и т. Д.) Между ними. Я думаю, что разделение пользовательского интерфейса и логики выборки данных является хорошей практикой по многим причинам (SSR, Routing, Testing), см. Этот блог.
Другой подход заключается в создании дерева компонентов, но подождите с сериализацией, пока все ваши обещания не будут выполнены. Именно такой подход, например, использует mobx-server-wait.