We will learn how to fire up an async request when the route changes.node
A mock server data:react
/** /api/index.js * Created by wanzhen on 7.6.2016. */ import { v4 } from 'node-uuid'; // This is a fake in-memory implementation of something // that would be implemented by calling a REST server. const fakeDatabase = { todos: [{ id: v4(), text: 'hey', completed: true, }, { id: v4(), text: 'ho', completed: true, }, { id: v4(), text: 'let’s go', completed: false, }], }; const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); export const fetchTodos = (filter) => delay(500).then(() => { switch (filter) { case 'all': return fakeDatabase.todos; case 'active': return fakeDatabase.todos.filter(t => !t.completed); case 'completed': return fakeDatabase.todos.filter(t => t.completed); default: throw new Error(`Unknown filter: ${filter}`); } });
We want to replace localStorge with mock server data, so remove the localStorge code:redux
// configureStore.js import { createStore } from 'redux'; import todoApp from './reducers'; const addLoggingToDispatch = (store) => { const rawDispatch = store.dispatch; // If browser not support console.group if (!console.group) { return rawDispatch; } return (action) => { console.group(action.type); console.log('%c prev state', 'color: gray', store.getState()); console.log('%c action', 'color: blue', action); const returnValue = rawDispatch(action); console.log('%c next state', 'color: green', store.getState()); console.groupEnd(action.type); return returnValue; }; }; const configureStore = () => { const store = createStore(todoApp); // If in production do not log it if (process.env.NODE_ENV !== 'production') { store.dispatch = addLoggingToDispatch(store); } return store; }; export default configureStore;
We want to fetch data inside the component: VisibleTodoList.js.api
The good place to fetch data is in 'componentDidMount' lifecycle: This will fetch the initial data, which only run once.react-router
Thats not enough, we still need when the filter changes, it also need to fetch data, for that we can use another lifecycle 'componentDidUpdate'.async
import {connect} from 'react-redux'; import {toggleTodo} from '../actions'; import TodoList from './TodoList'; import {withRouter} from 'react-router'; import {getVisibleTodos} from '../reducers'; import React, {Component} from 'react'; import {fetchTodos} from '../api'; class VisibleTodoList extends Component { // Fetch data when component mount componentDidMount() { fetchTodos(this.props.filter) .then((todos) => { console.log(this.props.filter, todos); }) } // Check the filter props, when it changes, fetch data again componentDidUpdate(prevProps) { if (this.props.filter !== prevProps.filter) { fetchTodos(this.props.filter) .then((todos) => { console.log(this.props.filter, todos); }) } } render() { return ( <TodoList {...this.props}/> ) } } const mapStateToProps = (state, {params}) => { const filter = params.filter || 'all'; //todos, filter Will available in props return { todos: getVisibleTodos(state, filter), filter, }; }; //re-assign the VisibleTodoList VisibleTodoList = withRouter(connect( mapStateToProps, {onTodoClick: toggleTodo} )(VisibleTodoList)); export default VisibleTodoList;