I'm developing a course scheduling application in react, and I'm using it as a chance to learn redux. There's a browse menu (implemented as the Browse component) that I'm currently designing and it displays the list of schools in the university upon load. When a user clicks on one of the schools, it displays a list of subjects within that school. However, I would like the schools to be displayed as a grid (two columns), and I would like the subjects to be displayed as a list (one column). They also may presumably require different props to be fed to the Browse component.
How would I go about doing this? Currently, I have a Browse component and a BrowseReduxContainer component. The BrowseReduxContainer component uses connect(), mapStateToProps, and mapDispatchToProps from react-redux to populate the props of Browse. This works fine when I'm just displaying schools, but I'm not sure how to modify the layout of Browse depending upon the state. Should I be giving connect() different components depending on the state? Or should I implement logic within the Browse component to check the prop and display a grid/list accordingly? Or something else entirely?
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
UPDATE:
My best guess at this point was to have different view components with their own appropriate props, perhaps called BrowseA and BrowseB and connect the appropriate one according to the state. I want to include this logic in mapDispatchToProps within BrowseReduxContainer, but then I realized the mapDispatchToProps function does not take state as a parameter. I'd love any suggestions!
See Question&Answers more detail:
os