I'm writing some generic Todo-List component, with the following features
- Pagination / Sorting
- Keep a part of the state within the URL (page, sort)
- Fetching the Data asynchronously using HTTP Requests (using redux-saga)
Now I'm trying to find a pattern for the "best" sequence of redux actions to get this working without problems.
I want the following behavior:
When Todo Component loads: Read URL Query Parameters and use this to fetch the data.
When the user clicks
sort by name
(ornext page
orfiler by xyz
) the Query Parameters within the URL should be updated and the next data should be fetched.
What my current code does:
I'm creating the props todos
, pagination
and sort
within react-redux's mapStateToProps
:
state => {
todos: state.venues.page,
pagination: parsePagination(state.router.location.search),
sorting: parseSorting(state.router.location.search)
}
Within the component I have lifecycle and methods like:
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));
}
Now the big questionmark:
Where / How should I run executeFetch
when sorting
or pagination
changes?
componentDidUpdate ? This looked promising, but: it creates an endless loop, because each
executeFetch
will trigger a component update, which then will runcomponentDidUpdate
again and again. I could check here ifpagination
and / orsorting
has changed, and then runexecuteFetch
, but I get a new object instance for those two props every time any prop changes, which requires then a deep equality check. Not nice.adding
executeFetch
at the end of eachonSortingChange
andonPaginationChange
. This seems to work, but feels a bit redundant. Another problem is, that I can't usethis.props.sorting
andthis.props.pagination
to runexecuteFetch
, because those props will aren't updated yet.
How do you solve this within your applications?
I think this is the scenario you're describing:
The loop requires that you do equality checking to only update the redux state under certain conditions. This is a problem created by having a component that re-renders from both the url state and redux state. Separating that logic into two components should work:
In practice that might look like:
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>
)
Where the todolist is not dispatching actions to modify the url, but just using <Link />
components or history.push
to add the pagination and sorting information.
来源:https://stackoverflow.com/questions/51734197/react-redux-with-router-location-pagination-sorting-and-fetch