I'm developing a large application with Redux and React and I decided to make some reusable components like custom checkboxes and radio buttons.
As I want to store this information into the Redux store to be able to debug state of the application easily and the same component have the same functionality everywhere, it seems a good idea to create reducers and actions for each component.
However Redux reducers return a new state and save it in the store with the name of the reducer as a key and this forbids having more than one component of the same type in the same page using the same actions and reducers but keeping different states.
I think there are two solutions to this problem:
Create different actions and reducers for each component that I use, even thought the component and it's functionalities are the same. This solutions doesn't seem a good solution because there will be a lot of redundant code.
Create actions with sufficient parameters to be able to differentiate each one in the reducer and that way change only the part of the state that is specified.
I went forward with the second option.
Actions file for the CheckBox component:
import {createAction} from 'redux-actions';
/****** Actions ******/
export const CHANGE_CHECKBOX_STATE = "CHANGE_CHECKBOX_STATE";
/****** Action creators ******/
export const changeCheckboxState = createAction(CHANGE_CHECKBOX_STATE, (block, name, state) => {
return {
block,
name,
state: {
checked: state,
}
};
});
Reducers file for the CheckBox component:
import {handleActions} from 'redux-actions';
import {CHANGE_CHECKBOX_STATE} from './CheckBox.actions';
export const checkBoxComponent = handleActions({
CHANGE_CHECKBOX_STATE: (state, action) => ({
[action.payload.block]: {
[action.payload.name]: action.payload.state
}
})
}, {});
I use block
to specify the page, name
to specify the name of the specific component (e.g. gender) and state as and object with the new state.
But this solution has some problems too:
I don't have enough experience with Redux and React to think of a better solution to this problem. But it seems to me that I'm missing something important about React-Redux relationship and this raises some questions:
Is it a good idea to store state of this reusable components into the Redux store?
Am I wrong in binding together React components with Redux actions and reducers?
Don't describe your Redux reducers (your overall application state) in terms of the components that consume that state. Track it the other way, describing your application state in a descriptive manner and then have your "dumb" components consume that descriptive state.
Rather than tracking "The state of this checkbox for the form related to foo", track "this boolean value of foo" and then have the checkbox consume that state.
An example store for the checkbox:
const initialState = {
someFooItem: { isCertainType: false }
};
export function foos(state = initialState, action) {
switch(action.type){
case(UPDATE_FOO_VALUE):
return {
...state,
[action.payload.id]: {
isCertainType: action.payload.isCertainType
}
}
}
}
An example checkbox consuming the store
class CheckBox extends React.Component {
render() {
return <input type="checkbox" checked={this.props.checked} />
}
}
The parent component
class ParentComponent extends React.Component {
render() {
return <CheckBox checked={this.foo.isCertainType} />
}
}
The fundamental mistake here is that you have 0 dumb components. Basic controls like checkboxes should be dumb components using just props, their parent having the responsibility to select and update the proper piece of state for a particular checkbox.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With