Let’s improve our file structure:
src/
action.js
actionTypes.js
reducer.js
Redux is all statement management. UI and Redux are two completely different concerns. Its like two supermarket sections.
That’s why we need to move all of our redux code to another separate folder:
src/
store/
-action.js
-actionTypes.js
-reducer.js
Let’s go further. Let’s group them into features. Each feature should have the standard action, actionType, and reducer files.
Dux Pattern – Bundle of action types, actions, and reducers for a specific domain. Instead of folders to group these three things together, we simply use one file. It is much more maintainable.
Implement Dux Pattern
In src, create store folder. In your store folder, create file called questions.js.
ducks pattern rules:
1) reducer must have ‘export default
2) export individual action creators
3) action types are implementation detail (no need for export)
so, action types:
1 2 3 4 |
// action types const QUESTION_ADDED = 'questionAdded'; const QUESTION_REMOVED = 'questionRemoved'; const QUESTION_ANSWER = 'questionAnswer'; |
action creators:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// action creators export const questionAdded = description => ({ type: QUESTION_ADDED, payload: { description } }); export const questionAnswer = (id, answer) => ({ type: QUESTION_ANSWER, payload: { id, answer } }); |
we export them so that other files can use them if need be.
Finally, our reducer, which needs to have ‘export default’:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// reducer let lastId = 0; export default function reducer(state = [], action) { switch(action.type) { case QUESTION_ADDED: return [ ...state, { id: ++lastId, description: action.payload.description, answer: null } ]; case QUESTION_REMOVED: return state.filter(question => question.id !== action.payload.id); case QUESTION_ANSWER: return state.map(question => { if (question.id !== action.payload.id) { return question; } else { return { ...question, answer: action.payload.answer } } }); default: return state; } } |
Configuring the Store
1 2 3 4 5 6 7 8 9 |
import { createStore } from 'redux'; import reducer from './questions'; export default function configureStore() { const store = createStore( reducer, ); return store; |
Finally, in order to use our store, in index.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import configureStore from './store/configureStore'; import { questionAdded } from './store/questions'; const store = configureStore(); store.subscribe( () => { console.log('store changed!', store.getState()); }); store.dispatch(questionAdded('what color is the sky')); store.dispatch(questionAdded('what color is the ground')); store.dispatch(questionAdded('what color are my eyes')); store.dispatch(questionAdded('what color is my hair')); store.dispatch(questionAdded('what color is the universe')); console.log(store.getState()); |
Now, your redux files with all those features won’t be cluttered. If you have ten features, you don’t have to scroll through 30 files. All you have is 10, and they’ve neatly packed their action, action types, and reducer into one file.