2

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 (or next page or filer 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 run componentDidUpdate again and again. I could check here if pagination and / or sorting has changed, and then run executeFetch, 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 each onSortingChange and onPaginationChange. This seems to work, but feels a bit redundant. Another problem is, that I can't use this.props.sorting and this.props.pagination to run executeFetch, because those props will aren't updated yet.

How do you solve this within your applications?

1
  • I think I have a pretty good answer for this. Did you come with anything yet? Commented Aug 8, 2018 at 22:08

1 Answer 1

1

I think this is the scenario you're describing:

enter image description here

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:

enter image description here

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. I'm using connected-react-router, though basically URL should be part of redux state. The approach looks interesting. But I guess you're missing the last part: The Component will also update the URL. When the user clicks "next page", the URL has to change. Could you add some more code for this use case?
Just use links? <Link /> components?
Also I think syncing the url state with redux is a bad idea, but that's just me
Links won't work for all scenarios. For example I have some kind of "live-search". While the user is typing in the search input box, the URL automatically changes (todos?page=1&searchQuery=test) and the search executes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.