Redux: Fetching Data on Route Change

Dan Abramov
InstructorDan Abramov

Share this video with your friends

Send Tweet
Published 6 years ago
Updated 3 years ago

We will learn how to fire up an async request when the route changes.

[00:00] I'm removing the fetch todos API call from my entry point because I want to fetch the todos inside my component. The component that displays and selects the todos is the visible todo list. I'm placing the fetch todos import into the visible todo list file.

[00:20] The visible todo list component is generated by the connect, and with router calls that each generate an intermediate component that inject props. A good place to call the API would be inside componented mount life cycle hook.

[00:37] Since I can't override the life cycle hooks of generated components, I have to create a new React component. I'm importing React and the component base class from React, and I will declare a React component class called visible todo list.

[00:54] It extends the React base component class. I'm defining the rend method, and I still want to render the presentational to the list component exactly. The only purpose of adding this new class is to add the life cycle hooks. I will pass any props down to the todo list.

[01:16] Since the visible todo list is defined as a class above, I can't declare another constant with the same name, but I can reassign the visible todo list binding to point to the wrapped component. Now I'm changing the connect call to wrap my new class instead.

[01:33] The component generated by the connect call will render the visible todo list class I defined. The result of the connect, and with router wrapping calls is the final todo list component that I export from the file.

[01:52] Now I will define the componented mount life cycle hook inside my visible todo list component class. When the component mounts, I want to fetch the todos for the current filter. It will be convenient to have the filter directly available as a prop.

[02:09] I am changing map state props to calculate the filter from params, just like it used to, but to also pass it as one of the properties on the return object. I will get both the todos and the filter itself inside the visible todo list component.

[02:28] Going back to the life cycle method, I can use this props filter inside componented mount now. When the todos are fetched, fetch todos returns a promise. I can use the then method to access the resolved todos, and to log the current filter, and the todos I just received from the fake backend.

[02:49] If I run the app now, I will see the all filter being printed, and the todos corresponding to the all filter. However, as I change the filter, nothing happens, because componented mount only runs once. To fix this, I am adding a second life cycle hook called componented update.

[03:10] It receives the previous props as an argument. I can compare the current and the previous values of the filter. If the current filter is not the same as the previous filter, it's time to fetch the todos for the current filter.

[03:28] I'm writing exactly the same code. When the todos are fetched, I want to print the current filter, and the corresponding todos. Clicking on a link now changes the route, and so it changes the filter prop. As a result, we fetch the data in the life cycle hooks.

~ 6 years ago

Would this following achieve the same thing with the same performance as the componentDidUpdate part? componentWillReceiveProps(nextProps) { if(this.props.filter !== nextProps.filter) { fetchTodos(nextProps.filter).then(todos => ...) } }

Federico Garcia
Federico Garcia
~ 5 years ago

Could you explain when to use componentWillReceiveProps and when componentDidUpdate? In every tutorial I see, people always use componentWillReceiveProps...

~ 4 years ago

Regarding the 'Link' component found within 'FilterLink', the 'All' link was not functioning. In order to get it to work I needed to have filter = '/' instead of an empty string when the conditional is true:

filter === 'all' ? '/' : filter (edited filter = '/')


filter === 'all' ? '' : filter (original filter = '')

Link Component below,

Link to={filter === 'all' ? '/' : filter} activeStyle={{ textDecoration: 'none', color: 'black', }} > {children} Link

Srikanth  Dasari
Srikanth Dasari
~ 4 years ago


github link is broken, can you please add it?