在渲染服务器端之前获取数据
Fetching data before rendering server side
现在我发现 Este.js 并且我对同构应用程序有一个小问题。我不明白如何在使用 renderToString() 呈现服务器端之前进行 api 调用。
一种解决方案是使用 React Router 在路由器级别获取所有数据。根据顶级路由,我可以预测需要哪些数据,进行 api 调用,然后调用 React.renderToString.
很好,但我仍然必须在组件级别和路由器级别声明数据依赖性。我最终将相同的代码写了两次,但我认为这不是最好的方法。
编辑:好的,现在我可以做一些我想做的事了。使用 React-Router 和这个 link 我已经能够做到以下几点:
给出这个全局应用程序状态,我想在指向 /todos 时预取 todos
initialstate.js
{
auth: {
data: null,
form: null
},
examples: {
editable: {
state: null,
text: 'Some inline-editable text.'
}
},
i18n: {
formats: {},
locales: initialLocale,
messages: messages[initialLocale]
},
pendingActions: {},
todos: {
editables: {},
newTodo: {
title: ''
},
list: [{
id: 1,
title: 'first todo yipiyo'
}]
},
users: {
viewer: null
}
}
todos.react.js
在 todo 组件中,我声明了一个静态函数 fetchData。因为我想在我的 appState 中检索正确的密钥,所以我将 'list' 作为参数传递。感觉很脏。
class Todos extends Component {
static fetchData(){
return actions.loadAllTodos('list');
}
componentDidMount(){
Todos.fetchData();
}
render() {
...
}
}
actions.js
Api 调用和其他东西,我将密钥传递给 promise - 感觉很老套
export function loadAllTodos(key) {
const promise = new Promise((resolve, reject) => {
Api.get()
.then(res => {
res.key = key; //hacky time
resolve(res)
})
.catch(err => {
reject(err);
})
});
return dispatch(loadAllTodos, promise);
}
render.js
router.run((Handler, routerState) => {
var promise = Promise.all(routerState.routes
.filter(route => route.handler.fetchData)
.map(route => {
return route.handler.fetchData();
})
);
promise.then(resp => {
console.log(resp);
//Displays :
[ { id: 2, title: 'Im a second todo' },{ id: 3, title: 'I like todo' },
cursor: 'list' ]
//Some stuff to add resp to appState, using the correct key, yey iso+api=win
appState = mergeThisWithMagic(appState, resp);
const html = preloadAppStateThenRenderHtml(Handler, appState);
const notFound = routerState.routes.some(route => route.name ===
'not-found');
const status = notFound ? 404 : 200;
res.status(status).send(html);
resolve();
});
});
如您所见,我将创建一个函数来使用更新后的待办事项列表更新 appState。
做这一切可以吗?请给我一些反馈,因为我觉得我正走在一条黑暗的道路上:(.
我在我的同构服务器端应用程序中完成了这个,方法是将我的 fetchData 函数放在组件的 statics
对象中,并使用承诺等待所有数据返回后再将应用程序渲染为字符串.
然后您将通过 props 将返回的数据传递给渲染的组件。这个例子对我开发这个应用程序很有帮助。 React Router Mega Demo.
现在我发现 Este.js 并且我对同构应用程序有一个小问题。我不明白如何在使用 renderToString() 呈现服务器端之前进行 api 调用。
一种解决方案是使用 React Router 在路由器级别获取所有数据。根据顶级路由,我可以预测需要哪些数据,进行 api 调用,然后调用 React.renderToString.
很好,但我仍然必须在组件级别和路由器级别声明数据依赖性。我最终将相同的代码写了两次,但我认为这不是最好的方法。
编辑:好的,现在我可以做一些我想做的事了。使用 React-Router 和这个 link 我已经能够做到以下几点:
给出这个全局应用程序状态,我想在指向 /todos 时预取 todos
initialstate.js
{
auth: {
data: null,
form: null
},
examples: {
editable: {
state: null,
text: 'Some inline-editable text.'
}
},
i18n: {
formats: {},
locales: initialLocale,
messages: messages[initialLocale]
},
pendingActions: {},
todos: {
editables: {},
newTodo: {
title: ''
},
list: [{
id: 1,
title: 'first todo yipiyo'
}]
},
users: {
viewer: null
}
}
todos.react.js
在 todo 组件中,我声明了一个静态函数 fetchData。因为我想在我的 appState 中检索正确的密钥,所以我将 'list' 作为参数传递。感觉很脏。
class Todos extends Component {
static fetchData(){
return actions.loadAllTodos('list');
}
componentDidMount(){
Todos.fetchData();
}
render() {
...
}
}
actions.js
Api 调用和其他东西,我将密钥传递给 promise - 感觉很老套
export function loadAllTodos(key) {
const promise = new Promise((resolve, reject) => {
Api.get()
.then(res => {
res.key = key; //hacky time
resolve(res)
})
.catch(err => {
reject(err);
})
});
return dispatch(loadAllTodos, promise);
}
render.js
router.run((Handler, routerState) => {
var promise = Promise.all(routerState.routes
.filter(route => route.handler.fetchData)
.map(route => {
return route.handler.fetchData();
})
);
promise.then(resp => {
console.log(resp);
//Displays :
[ { id: 2, title: 'Im a second todo' },{ id: 3, title: 'I like todo' },
cursor: 'list' ]
//Some stuff to add resp to appState, using the correct key, yey iso+api=win
appState = mergeThisWithMagic(appState, resp);
const html = preloadAppStateThenRenderHtml(Handler, appState);
const notFound = routerState.routes.some(route => route.name ===
'not-found');
const status = notFound ? 404 : 200;
res.status(status).send(html);
resolve();
});
});
如您所见,我将创建一个函数来使用更新后的待办事项列表更新 appState。
做这一切可以吗?请给我一些反馈,因为我觉得我正走在一条黑暗的道路上:(.
我在我的同构服务器端应用程序中完成了这个,方法是将我的 fetchData 函数放在组件的 statics
对象中,并使用承诺等待所有数据返回后再将应用程序渲染为字符串.
然后您将通过 props 将返回的数据传递给渲染的组件。这个例子对我开发这个应用程序很有帮助。 React Router Mega Demo.