Tell me, people, I alone experience a little mental itch
from the need to write something here such? :
export const ADD_TODO = 'ADD_TODO' export const DELETE_TODO = 'DELETE_TODO' export const EDIT_TODO = 'EDIT_TODO' export const COMPLETE_TODO = 'COMPLETE_TODO' export const COMPLETE_ALL = 'COMPLETE_ALL' export const CLEAR_COMPLETED = 'CLEAR_COMPLETED'
For some reason I think that there is not and sometimes meeting someone’s code
if (action.type === ADD_TODO) { // ... }
instead of a switch-case core, I understand that I’m not the only perfectionist in the world who suffers from this "a little bit wrong" in classic Redux
If you, dear reader, know this pain, rejoice! under the cut there is a medicine with only two lines of code :)
The situation is especially sad when you try to sort out a large project with a complicated UI. You see what action methods the component calls, open the file with these actions and it’s good if the constants are called intuitively there, but there are situations when you start looking in all the reducers where they go.
In essence, dispatch is a Store method, similar in meaning to the emit method of the good old EventEmitter and in terms of the classic event model, in fact, the Store is subscribed to events whose names are called action types and which are usually given in the form of the aforementioned constants, due to than I constantly had a question, why should I keep it somewhere else, and besides, repeatedly resorting to such an absurd duplication of code? The original idea is clear, we need to hedge against conflicts and provide some consistency between action and reductors, but is it not impossible to make it more elegant?
I understand that people are different and if anyone has a reasoned objection to this light discomfort from working with the Redux code, I will be happy to hear any opinions in the comments, but let those who share this feeling, imagine redux-refine
The basic idea is simple:
I propose to use instead of a switch-case hash indexed by the type of actions, since the object cannot have the same properties, which eliminates conflicts within a single reducer, and also allows you to export types of actions for the module from which they are dispatched
Also, this approach provides pure code connectivity, following the logic of one way binding and reflecting the direction of data flow in the application, namely:
we see in the component what methods of the module with actions it uses, and in the module with actions we see how it sends the actions to the reducers.
At the request of tmnhy I will explain with a clear example:
in action we do this:
import { actionTypes as types1 } from 'reducers/reducer1' import { actionTypes as types2 } from 'reducers/reducer2' const { ACTION_1_1, ACTION_1_2, ACTION_1_3 } = types1 const { ACTION_2_1, ACTION_2_2, ACTION_2_3 } = types2
in rediresers like this:
reducer1:
import { getActionTypes, connectReducers } from 'redux-refine' export const initialState = { value1: 0, value2: '', value3: null, } const reducers = { ACTION_1_1: (state, {value1}) => ({...state, value1}), ACTION_1_2: (state, {value2}) => ({...state, value2}), ACTION_1_3: (state, {value3}) => ({...state, value3}), } export const actionTypes = getActionTypes(reducers) export default connectReducers(initialState, reducers)
reducer2:
import { getActionTypes, connectReducers } from 'redux-refine' export const initialState = { value1: 0, value2: '', value3: null, } const reducers = { ACTION_2_1: (state, {value1}) => ({...state, value1}), ACTION_2_2: (state, {value2}) => ({...state, value2}), ACTION_2_3: (state, {value3}) => ({...state, value3}), } export const actionTypes = getActionTypes(reducers) export default connectReducers(initialState, reducers)
in the place where you prefer to combine the redusers everything is as before:
import { combineReducers } from 'redux' import reducer1, { initialState as stateSection1 } from './reducer1' import reducer2, { initialState as stateSection2 } from './reducer2' export const intitialState = { stateSection1, stateSection2 } export default combineReducers({ stateSection1: reducer1, stateSection2: reducer2 })
Yes, of course, I understand that this is a very petty innovation, but it’s much more pleasant for me to work with the code from this style :)
And please, do not judge strictly, if that - this is my first post on Habré
UPD:
Snatching a lot of comments, interesting, but expressed with varying degrees of misunderstanding about what it is - redux-refine, I decided to add an even more detailed explanation:
Here is what I did:
1 Replaced the switch-case structure with a choice of key in hash:
this
function reducer(state, {type, data}){ switch(type) { case 'one': return {...state, ...data}; case 'two': return {...state, ...data}; case 'three': return {...state, ...data}; default: return state; } }
replaced it
function reducer(state, {type, data}){ return ({ one: {...state, ...data}, two: {...state, ...data}, three: {...state, ...data} })[type] || state; }
2 Brought a hash from the function osprey so as not to recreate it with each call, and each property of this hash made by method pure function, which passes the necessary data in the arguments.
const reducers = { one: (state, data) => ({...state, ...data}), two: (state, data) => ({...state, ...data}), three: (state, data) => ({...state, ...data}) } function reducer(state, {type, data}){ return (redusers[type] || (state => state))(state, data); }
3 Instead of declaring constants, I used the export of hash keys, since they are unique by definition, thus creating the ability to import these keys in actions from reducer, which allows you to visually show with what reducer this module works with actions.
And please, do not fuss, because redux-refine works in exactly the same way as a classic reducer - just one to one, which is why I said that you can use it at the same time as the usual approach.
This is not some kind of new architecture, not some kind of new bells and whistles - it's just an improvement in the code-type and ensuring the visibility of the links between the modules of the classic editor.
Source: https://habr.com/ru/post/342894/