Joon Park Joon Park - 12 days ago 5
React JSX Question

Redux state changes on load even though no action has been dispatched

For some reason, when I load my webapp, the state 'currentView' is set to "subjects" instead of the initial value "schools" even though there was no action dispatched. Why is this the case?

actions.js

export function showSubjects(schoolId) {
return {
type: 'SHOW_SUBJECTS',
schoolId
};
}


browse.js

const initialState = {
currentView: 'schools',
schools: [{id: 'AAAA', name: 'aaaa'}, {id: 'BBBB', name: 'bbbb'}],
subjects: [{id: 'CCC', name: 'ccc'}, {id: 'DDD', name: 'ddd'}]
};

function browse(state = initialState, action) {
switch (action.type) {
case 'SHOW_SUBJECTS':
return {
...state,
currentView: 'subjects'
};
default:
return state;
}
}

export default browse;


BrowseReduxContainer.jsx

import { connect } from 'react-redux';
import { showSubjects } from '../actions/actions';
import Browse from '../components/Browse.jsx';

function propsFilter(state) {
switch (state.currentView) {
case 'schools':
return state.schools;
case 'subjects':
return state.subjects;
default:
throw new Error(`No such view: ${state.currentView}`);
}
}

const mapStateToProps = (state) => ({
schools: propsFilter(state)
});

const mapDispatchToProps = (dispatch) => ({
showSubjects: (schoolId) => {
dispatch(showSubjects(schoolId));
}
});

const BrowseReduxContainer = connect(mapStateToProps, mapDispatchToProps)(Browse);

export default BrowseReduxContainer;


Browse.jsx

import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';

const Browse = (props) => (
<div>
{props.schools.map((school) => (
<RaisedButton key={school.id} label={school.name} onClick={props.showSubjects(school.id)} />
))}
</div>
);

export default Browse;


Other relevant files, if necessary, can be viewed here: https://github.com/Joonpark13/serif.nu/tree/feature/browse

Answer

Your RaisedButton causes the issue:

<RaisedButton key={school.id} label={school.name} onClick={props.showSubjects(school.id)} />

You execute showSubjects in the onClick handler instead of passing a reference. Instead, it should be onClick={() => props.showSubjects(school.id)} so that the function is only executed after the click.

As an alternative, you can also modify your mapDispatchToProps:

const mapDispatchToProps = (dispatch) => ({
  showSubjects: (schoolId) => () => {
    dispatch(showSubjects(schoolId));
  }
});
Comments