React Redux 与路由器位置、分页/排序和获取
React Redux with Router Location, Pagination / Sorting and Fetch
我正在编写一些具有以下功能的通用待办事项列表组件
- 分页/排序
- 保留URL内的一部分状态(分页,排序)
- 使用 HTTP 请求异步获取数据(使用 redux-saga)
现在我正在尝试为 "best" redux 操作序列找到一种模式,以使其正常工作。
我想要以下行为:
加载 Todo 组件时:读取 URL 查询参数并使用它来获取数据。
当用户单击 sort by name
(或 next page
或 filer by xyz
)时,URL 中的查询参数应更新,下一个数据应该被提取。
我当前代码的作用:
我正在 react-redux 的 mapStateToProps
:
中创建道具 todos
、pagination
和 sort
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));
}
现在打个大问号:
当 sorting
或 pagination
发生变化时,我应该在哪里/如何 运行 executeFetch
?
componentDidUpdate ? 这看起来很有希望,但是:它创建了一个无限循环,因为每个 executeFetch
都会触发组件更新,然后将运行 componentDidUpdate
一次又一次。我可以在这里检查 pagination
和/或 sorting
是否已更改,然后 运行 executeFetch
、 但是 我得到一个新对象每次任何 prop 更改时,这两个 props 的实例,这需要进行深度相等性检查。不好看
在每个 onSortingChange
和 onPaginationChange
的末尾添加 executeFetch
。这似乎可行,但感觉有点多余。另一个问题是,我不能使用 this.props.sorting
和 this.props.pagination
到 运行 executeFetch
,因为这些道具还没有更新。
您如何在您的应用程序中解决这个问题?
我认为这就是您描述的情况:
循环要求您进行相等性检查以仅在特定条件下更新 redux 状态。这是一个组件从 both url 状态和 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
添加分页和排序信息。
我正在编写一些具有以下功能的通用待办事项列表组件
- 分页/排序
- 保留URL内的一部分状态(分页,排序)
- 使用 HTTP 请求异步获取数据(使用 redux-saga)
现在我正在尝试为 "best" redux 操作序列找到一种模式,以使其正常工作。
我想要以下行为:
加载 Todo 组件时:读取 URL 查询参数并使用它来获取数据。
当用户单击
sort by name
(或next page
或filer by xyz
)时,URL 中的查询参数应更新,下一个数据应该被提取。
我当前代码的作用:
我正在 react-redux 的 mapStateToProps
:
todos
、pagination
和 sort
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));
}
现在打个大问号:
当 sorting
或 pagination
发生变化时,我应该在哪里/如何 运行 executeFetch
?
componentDidUpdate ? 这看起来很有希望,但是:它创建了一个无限循环,因为每个
executeFetch
都会触发组件更新,然后将运行componentDidUpdate
一次又一次。我可以在这里检查pagination
和/或sorting
是否已更改,然后 运行executeFetch
、 但是 我得到一个新对象每次任何 prop 更改时,这两个 props 的实例,这需要进行深度相等性检查。不好看在每个
onSortingChange
和onPaginationChange
的末尾添加executeFetch
。这似乎可行,但感觉有点多余。另一个问题是,我不能使用this.props.sorting
和this.props.pagination
到 运行executeFetch
,因为这些道具还没有更新。
您如何在您的应用程序中解决这个问题?
我认为这就是您描述的情况:
循环要求您进行相等性检查以仅在特定条件下更新 redux 状态。这是一个组件从 both url 状态和 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
添加分页和排序信息。