我有一個使用Redux和React路由器的通用React應用程序。我的一些路由包含的參數,在客戶端,將觸發一個AJAX請求來保存數據以供顯示。在服務器上,這些請求可以同步完成,並在第一個請求上呈現。如何使用React + Redux保護服務器端參數
我遇到的問題是這樣的:在路由組件上調用任何生命週期方法(例如componentWillMount
)時,發送將反映在第一個呈現中的Redux操作已經太晚了。
這裏是我的服務器端呈現代碼的簡化視圖:
routes.js
export default getRoutes (store) {
return (
<Route path='/' component={App}>
<Route path='foo' component={FooLayout}>
<Route path='view/:id' component={FooViewContainer} />
</Route>
</Route>
)
}
server.js
let store = configureStore()
let routes = getRoutes()
let history = createMemoryHistory(req.path)
let location = req.originalUrl
match({ history, routes, location }, (err, redirectLocation, renderProps) => {
if (redirectLocation) {
// redirect
} else if (err) {
// 500
} else if (!renderProps) {
// 404
} else {
let bodyMarkup = ReactDOMServer.renderToString(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>)
res.status(200).send('<!DOCTYPE html>' +
ReactDOMServer.renderToStaticMarkup(<Html body={bodyMarkup} />))
}
})
當FooViewContainer
組分是在服務器上構建,其第一個渲染的道具已經是fi了固定的。我第一次致電render()
時,我發送給商店的任何行爲都不會反映出來,這意味着它們不會反映在頁面請求上的內容中。
React Router傳遞的id
參數本身並不適用於第一次渲染。我需要同步保存這個值到一個適當的對象。我應該在哪裏補水?
一種解決方案是將其內聯放入render()
方法中,以用於在服務器上調用的實例。這對我來說顯然是不正確的,因爲1)它在語義上毫無意義,2)它收集的任何數據都不會被正確地分派到商店。
我見過的另一個解決方案是爲Router鏈中的每個容器組件添加一個靜態的fetchData
方法。例如是這樣的:
FooViewContainer.js
class FooViewContainer extends React.Component {
static fetchData (query, params, store, history) {
store.dispatch(hydrateFoo(loadFooByIdSync(params.id)))
}
...
}
server.js
let { query, params } = renderProps
renderProps.components.forEach(comp =>
if (comp.WrappedComponent && comp.WrappedComponent.fetchData) {
comp.WrappedComponent.fetchData(query, params, store, history)
}
})
我覺得一定有比這更好的辦法。它不僅看起來相當不雅(.WrappedComponent
是一個可靠的界面?),但它也不適用於更高階的組件。如果任何路由組件類被除connect()
之外的任何東西包裝,則此操作將停止工作。
我在這裏錯過了什麼?