reactjs - 在react-router转换期间我应该如何更新redux存储?

标签 reactjs react-router redux

我遇到了如何在发生 react 路由器转换时更新存储的问题。

在我当前的实现中(如下),在呈现下一页之前更新存储。当当前页面根据下一页的数据获取商店更新时,就会出现问题:(1) 当前页面毫无意义地呈现(它订阅了商店更新),因为更新的商店是针对下一页的 (2)当前页面在渲染时中断,因为更新的存储仅包含下一页的数据。

superagent
  .get(opts.path)
  .set('Accept', 'application/json')
  .end((err, res) => {
    let pageData = res && res.body || {};
    store.dispatch(setPageStore(pageData));
    render(store);
  });

反过来也是有问题的,在更新商店之前渲染下一页。现在的问题是渲染时的下一个分页符,因为下一页所需的数据在存储更新之前不存在。

我要么滥用了库,要么我的架构不完整,或者其他什么。帮忙!

示例代码的其余部分:

应用程序

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')
  );
}

Action 和 reducer

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};
}

最佳答案

您可以使用redux-thunk中间件依次分派(dispatch)多个操作

查看精彩 redux doc #Async Actions section了解更多!

因此,您的获取数据操作创建器将如下所示:

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'))
      });
  }
}

如您所见,只需执行 store.dispatch(fetchSomeData('somePath')),它就会自动首先调用 fetchStarted 来显示微调器,当过程完成后,调用 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...

如果你想将最新版本的react-router与redux-simple-router(连同redux-thunk)一起使用,check out this repo !

您可以在这些文件中找到其商店配置、路由器设置:

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

关于reactjs - 在react-router转换期间我应该如何更新redux存储?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34444154/

相关文章:

javascript - 如果 match.params 与数据库中的 ID 不匹配则重定向 | react 路由器 V4

javascript - ReactJS - 更改另一个组件呈现的内容的组件

javascript - Redux + React-Router 不渲染

reactjs - 奇怪的 TS2322(类型不可分配)错误

reactjs - 如何禁用 Material-UI 对比度控制台错误?

javascript - 带有反应和验证器的 Redux 形式

javascript - d3.js水平条形图问题

reactjs - React Native 初始路由名称

reactjs - 将 React 应用程序部署到 IONOS - 页面刷新时出现 404

javascript - 我应该在初始渲染期间使用 redux 调度吗?