在浏览器上通过React + Redux中的状态数据进行前进/后退时内容不会更改

时间:2019-04-13 17:58:54

标签: javascript reactjs redux

我想提取subreddits并以列表形式显示给用户。当用户从选项菜单更改subreddit时,我将状态推送到浏览器历史记录。

实时演示https://react-7qfrxx.stackblitz.io

复制:

  1. 打开上方链接
  2. 从列表中选择frontend。列出后,再次选择reactjs
  3. 您将看到URL更改(附加subreddit)
  4. 现在按下浏览器的后退按钮并前进。
  5. 您会看到 URL发生更改,但是内容相同

实时编辑器https://stackblitz.com/edit/react-7qfrxx

AsyncApp.js Line 36

this.props.dispatch(push('/' + nextSubreddit))

如何在向后/向前按时向用户显示上一个或下一个缓存/状态?有人可以编辑我的在线应用程序以向我显示正确的方式吗?我试图解决这一问题,因为两天了,没有运气。


enter image description here

我需要执行此操作没有页面刷新。 (异步)

4 个答案:

答案 0 :(得分:2)

以前的解决方案不起作用,所以这是我的最新答案:我认为您最好的选择是听 LOCATION_CHANGE 动作类型/ strong>,然后在此处选择分派发送给您。 connected-react-router 项目中未记录使用 LOCATION_CHANGE ,但是旧项目的 docs 会做出反应-router-redux确实提到了它。

我们实际上可以创建一个中间件函数来完成此任务:

connected-react-router

下一步,将其添加到您的其他中间件中:

import { LOCATION_CHANGE } from 'connected-react-router'
import { selectSubreddit } from './actions';

export const listenRouteMiddleware = ({ dispatch, getState }) => (next) => (action) => {
  if (action.type === LOCATION_CHANGE) {
    const { pathname } = action.payload.location;
    if (pathname !== '/') {
      const pathArray = pathname.split('/');
      const selectSub = pathArray[pathArray.length - 1];
      next(action); // before dispatch, otherwise history breaks
      dispatch(selectSubreddit(selectSub));
      return;
    }
  }
  next(action);
}

更改更改处理程序,使其仅在选择以下选项时推送新网址:

import thunkMiddleware from 'redux-thunk'

import { createBrowserHistory } from 'history'
import { applyMiddleware, compose, createStore } from 'redux'
import { routerMiddleware } from 'connected-react-router'
import createRootReducer from './reducers'
import { listenRouteMiddleware } from './middleware';
export const history = createBrowserHistory()

export default function configureStore(preloadedState) {
  const store = createStore(
    createRootReducer(history), // root reducer with router state
    preloadedState,
    compose(
      applyMiddleware(
        listenRouteMiddleware,
        routerMiddleware(history), // for dispatching history actions
        thunkMiddleware
        // ... other middlewares ...
      ),
    ),
  )

  return store
}

仅此而已!要查看有效的示例,请查看:EditorApp

答案 1 :(得分:1)

您需要根据Route而不是状态来获取数据。选择下拉菜单时,仅更改路线。 您可以使用connected-react-router收听URL更改。更改路线后,它将根据该路线获取数据。

function mapStateToProps(state) {
  var { selectedSubreddit, postsBySubreddit } = state;

  // Listen to the connected-react-router API for URL change.
  selectedSubreddit = state.router.location.pathname === "/" ? "reactjs" : state.router.location.pathname.split("/")[1];

  const { isFetching, lastUpdated, items: posts } = postsBySubreddit[
    selectedSubreddit
  ] || {
    isFetching: true,
    items: []
  }

  return {
    selectedSubreddit,
    posts,
    isFetching,
    lastUpdated
  }
}

这是叉子。 _.set

这是固定的应用程序。 https://stackblitz.com/edit/react-wxfdea

URL已更新。

答案 2 :(得分:1)

当前解决方案的问题在于,您将selectedSubreddit状态值存储在两个位置-Redux和url。通常应避免这种状态重复。您正在使用connected-react-router库,因此还没有太多问题,但是在较大的应用程序中,这种事情可能很难管理。

在您的应用中,您还有两条路线,/frontend/reactjs,但是您没有定义任何<Route/>组件。

我认为您的组件结构应该更像

<Router>
  <>
    <Route exact path="/frontend" component={SubReddit}/>
    <Route exact path="/reactjs" component={SubReddit}/>
  </>
</Router>

然后在componentDidMount的{​​{1}}中,您只需检查路由器为当前选定的subreddit提供的<SubReddit/>道具。更改为另一个subreddit只需进行导航即可(为此使用react-router的location组件)。这样,URL便成为当前所选子Reddit的真实来源。

Redux仅用于管理subreddit帖子列表是完全矫kill过正,但如果可以练习将其用于实践,则是足够公平的。

答案 3 :(得分:0)

这不适用于您的原因是因为您仅从Redux状态读取subreddit名称,而不查看URL。您实际上可以通过查看路由器中的位置来从状态获取URL。

因此,一个简单的解决方法是始终根据URL来计算它,而不是将tail stdout作为Redux状态的单独部分进行存储和读取。如下更改selectedSubreddit中的mapStateToProps

AsyncApp.js