Tri*_*sie 9 reactjs react-router redux
我遇到了一个关于如何在发生react-router转换时更新存储的问题.
在我当前的实现(下面)中,在渲染下一页之前更新存储.当当前页面根据下一页的数据获得商店更新时会出现问题:(1)当前页面无意义地呈现(它订阅了商店更新),因为更新的商店用于下一页(2)渲染时的当前页面中断,因为更新的存储仅包含下一页的数据.
superagent
.get(opts.path)
.set('Accept', 'application/json')
.end((err, res) => {
let pageData = res && res.body || {};
store.dispatch(setPageStore(pageData));
render(store);
});
Run Code Online (Sandbox Code Playgroud)
反过来也有问题,在更新商店之前渲染下一页.现在的问题是渲染的下一个分页符,因为在更新存储之前,下一页所需的数据不存在.
我要么滥用库,要么我的架构不完整,或其他什么.救命!
其余的示例代码:
const React = require('react');
const Router = require('react-router');
const {createStore} = require('redux');
const {update} = React.addons;
const routes = require('./routes'); // all the routes
let store = {};
let initialLoad = true;
Router.run(routes, Router.HistoryLocation, (Handler, opts) => {
if(initialLoad) {
initialLoad = false;
// hydrate
const initialState = JSON.parse(document.getElementById('initial-state').text);
store = createStore(appReducer, initialState);
render(store);
} else {
superagent
.get(opts.path)
.set('Accept', 'application/json')
.end((err, res) => {
let pageData = res && res.body || {};
store.dispatch(setPageStore(pageData));
render(store);
});
}
});
function render(store) {
React.render(
<Provider store={store} children={() => <Handler/>} />,
document.getElementById('react')
);
}
Run Code Online (Sandbox Code Playgroud)
function appReducer(state = {}, action) {
switch(action.type) {
case 'SET_PAGE_STORE':
return update(state, {$merge: action.pageData});
default:
return reduce(state, action);
}
}
const reduce = combineReducers({
// ..all the reducers
});
function setPageStore(pageData) {
return {type: 'SET_PAGE_STORE', pageData};
}
Run Code Online (Sandbox Code Playgroud)
您可以使用redux-thunk中间件一个接一个地分派多个操作
有关更多信息,请参阅awesome redux doc #Async Actions部分!
所以你的fetch数据动作创建者看起来像这样:
function fetchSomeData(path) {
return dispatch => {
// first dispatch a action to start the spinner
dispatch(fetchStarted(path))
return superagent.get(path)
.set('Accept', 'application/json')
.end((err, res) => {
if (err) {
dispatch(fetchDataError(err)) // handle error
} else {
let pageData = res && res.body || {};
dispatch(fetchSuccess(pageData)); // do whatever you want when fetch is done here
// such as this action from redux-simple-router to change route
dispatch(pushPath('/some/path'))
});
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,通过简单地执行store.dispatch(fetchSomeData('somePath')),它将自动首先调用fetchStartedshow spinner,当进程完成时,调用fetchSuccess(path)隐藏微调器,更新状态,重新渲染...等,或调用fetchError(err)以显示错误消息,并且您可以调用操作来在此过程中的任何位置更改路径!
(你不需要redux-simple路由器,如果你不喜欢它,你可以调用history.pushState(null, '/some/path')改变路由,我只是发现redux-simple-router非常方便,因为你不需要传递历史到处,加上你UPDATE_PATH如果你想跟踪路线变化,你可以听一个动作)
此外,我建议redux-simple-router当您将react-router与redux一起使用时,它允许您使用UPDATE_PATH操作类型和pushPath更改路径的操作来查看路径更改.另外,我注意到你使用的是反应路由器的过时版本......
如果你想使用最新版本的react-router和redux-simple-router(以及redux-thunk),请查看这个回购!
你可以在这些文件中找到它的商店配置,路由器设置:
src/main.js // calls reactDOM.render(<Root />, ...) to render <Root />
src/containers/Root.js // <Root /> is a wrapper for react-redux <Provider />
src/redux/configureStore.js // store configuration, how redux-thunk middleware is configured
src/routes/index.js // routes are defined here
Run Code Online (Sandbox Code Playgroud)
一种解决方案是使您的页面兼容不完整的数据,直到获取新的页面数据。然后,您可以推送新路径,它将尽可能立即渲染,并且您的 UI 组件渲染旋转器(或类似的东西),直到获取下一页的数据并将其分派到存储。在第二遍时,页面将完全重新呈现。
我想到的另一件事是,理想情况下,您的商店的形状是这样的:您的所有页面从根本上与其可能处于的所有可能状态兼容,而不会发生冲突。这将允许您执行诸如预取数据之类的操作,这可以解锁最小化转换时间以及缓存先前视图的方法。毕竟,当单页架构仍然需要往返时,它并不是特别有用。
| 归档时间: |
|
| 查看次数: |
1174 次 |
| 最近记录: |