使用路由器位置、分页/排序和获取来响应 Redux

IT技术 reactjs redux pagination redux-saga query-parameters
2021-05-24 02:43:39

我正在编写一些通用的 Todo-List 组件,具有以下功能

  • 分页/排序
  • 在 URL 中保留一部分状态(页面、排序)
  • 使用 HTTP 请求异步获取数据(使用 redux-saga)

现在,我正在尝试为 redux 操作的“最佳”序列找到一种模式,以使其正常工作。

我想要以下行为:

  • 当 Todo 组件加载时:读取 URL 查询参数并使用它来获取数据。

  • 当用户单击sort by name(或next pagefiler by xyz)URL 中的查询参数应更新并应获取下一个数据。

我当前的代码做什么:

我正在创建 props todospaginationsort在 react-redux 中mapStateToProps

state => {
    todos: state.venues.page,
    pagination: parsePagination(state.router.location.search),
    sorting: parseSorting(state.router.location.search)
}

在组件中,我有生命周期和方法,例如:

componentDidMount() {
    // these props come from redux's "mapStateToProps"
    dipatch(executeFetch(this.props.pagination, this.props.sorting));
}

onSortingChange = (sorting) => {
    // this will use connected-react-router's "push"
    // to update the browser's URL
    dispatch(dispatchSetSortingQueryParam(sorting));
}

onPaginationChange = (pagination) => {
    // same as "onSortingChange"
    dispatch(setPaginationQueryParam(sorting));
}

现在是大问号:

在哪里/我应该如何运行executeFetch时,sortingpagination改变?

  • 组件DidUpdate ?这看起来很有希望,但是:它创建了一个无限循环,因为每个executeFetch都会触发一个组件更新,然后会componentDidUpdate一次又一次地运行我可以在这里检查pagination和/或sorting是否已更改,然后运行executeFetch但是每次任何props更改时,我都会为这两个props获取一个新对象实例,这需要进行深度相等性检查。不太好。

  • executeFetch在每个onSortingChange的末尾添加onPaginationChange这似乎有效,但感觉有点多余。另一个问题是,我无法使用this.props.sortingthis.props.pagination运行executeFetch,因为这些props尚未更新。

你如何在你的应用程序中解决这个问题?

1个回答

我认为这就是您所描述的场景:

在此处输入图片说明

该循环要求您进行相等性检查以仅在特定条件下更新 redux 状态。这是通过具有一个组件从该重新呈现创建了一个问题链接状态和终极版的状态。将该逻辑分成两个组件应该可行:

在此处输入图片说明

在实践中可能看起来像:

let App = () => (
  <Router>
    <>
      <Route component={class extends Component {
        componentDidUpdate() {
          let { pagination, sorting } = parse(window.location.search)
          dipatch(executeFetch(pagination, sorting));
        }
        render() { return null }
      }} />
      <Route path="/todo_list" component={props => (
        <div>
          {/* change url via link */}
          <Link to={...}>Change Page</Link>
          {/* change url programatically */}
          <input
            onChange={e => props.history.push(...)}
          />
        </div>
      )} />
    </>
  </Router>
)

其中 todolist 不调度操作来修改 url,而只是使用<Link />组件或history.push添加分页和排序信息。