Vincas Stonys Vincas Stonys - 2 months ago 17
React JSX Question

React router + redux navigating back doesn't call componentWillMount

Currently I pre-load data from api in container component's lifecycle method componentWillMount:

componentWillMount() {
const { dept, course } = this.props.routeParams;
this.props.fetchTimetable(dept, course);
}


It is called when user navigates to route
/:dept/:course
, and it works fine, until you navigate from let's say:
/mif/31
to
/mif/33
and then press back button. The component is not actually reinitialized, so the lifecycle method is not called, and the data isn't reloaded.

Is there some sort of way to reload data in this case? Should I maybe use another method of preloading data? I see react router emits
LOCATION_CHANGE
event on any location change, including navigating back, so maybe I can somehow use that?

If it matters, here's is how I implement data loading:

import { getTimetable } from '../api/timetable';

export const REQUEST_TIMETABLE = 'REQUEST_TIMETABLE';
export const RECEIVE_TIMETABLE = 'RECEIVE_TIMETABLE';

const requestTimetable = () => ({ type: REQUEST_TIMETABLE, loading: true });
const receiveTimetable = (timetable) => ({ type: RECEIVE_TIMETABLE, loading: false, timetable });

export function fetchTimetable(departmentId, courseId) {
return dispatch => {
dispatch(requestTimetable());
getTimetable(departmentId, courseId)
.then(timetable => dispatch(receiveTimetable(timetable)))
.catch(console.log);
};
}

Answer

You need to use componentWillReceiveProps to check if new props (nextProps) are same as existing props (this.props). Here's relevant code in Redux example: https://github.com/reactjs/redux/blob/e5e608eb87f84d4c6ec22b3b4e59338d234904d5/examples/async/src/containers/App.js#L13-L18

componentWillReceiveProps(nextProps) {
  if (nextProps.dept !== this.props.dept || nextProps.course !== this.props.course) {
    dispatch(fetchTimetable(nextProps.dept, nextProps.course))
  }
}
Comments