'React useReducer: How to have a dispatch function update a object nested in initial state object
Consider the following:
I have an initial state object:
const INITIAL_STATE = {
visited: false,
isSaveAllowed: false,
isWithdrawAllowed: false,
isContinuationAllowed: false
}
Which is being copied/spread to a collection of objects; I want each of those objects in viewDataInitialState to have those properties from INITIAL_STATE:
const viewDataInitialState = {
detailsViewData: { ...INITIAL_STATE },
discountsViewData: { ...INITIAL_STATE },
documentsViewData: { ...INITIAL_STATE },
fieldRepViewData: { ...INITIAL_STATE }
}
This is my reducer:
function viewDataReducer (state, { type, payload }) {
function makeFieldUpdater (payload) {
return function (payload = {}) {
return { ...state, ...{ isSaveAllowed: payload.isSaveAllowed } }
}
}
switch (type) {
case 'MAKE_FIELD_UPDATER': {
makeFieldUpdater(payload)
}
default:
return state
}
function ViewDataProvider ({ children }) {
const [state, dispatch] = React.useReducer(viewDataReducer, viewDataInitialState)
function updateDetailsViewData(kindOfData) {
dispatch({
type: 'UPDATE_DETAILS_VIEW_DATA',
payload: kindOfData
})
}
return (
<ViewDataStateContext.Provider value={{ state }}>
<ViewDataDispatch.Provider
value={{
updateDetailsViewData,
}}
>
{children}
</ViewDataDispatch.Provider>
</ViewDataStateContext.Provider>
)
}
How could I get updateDetailsViewData to update the correct state object?
Example, I use the dispatcher in a child, but I want it to update fieldRepViewData for instance?
function Child(){
const { updateDetailsViewData } = viewDataDispatch()
// later
updateDetailsViewData({ isAllowed: true}) // please sir update only fieldRepViewData
}
In another implementation of this we were passing the setState function to makeFieldUpdater
function makeFieldUpdater (setStateFn) {
/**
* Pass an object. Immer will replace state props as needed
* @param {Object} payload
*/
return function (payload = {}) {
setStateFn(
produce((draft) => Object.assign(draft, payload))
)
}
}
function useViewData () {
const [detailsViewData, setDetailsViewData] = useState({ ...INITIAL_STATE })
const [discountsViewData, setDiscountsViewData] = useState({ ...INITIAL_STATE })
const [documentsViewData, setDocumentsViewData] = useState({ ...INITIAL_STATE })
const [fieldRepViewData, setFieldRepViewData] = useState({ ...INITIAL_STATE })
return {
detailsViewData,
updateDetailsViewData: makeFieldUpdater(setDetailsViewData),
resetDetailsViewData: makeFieldResetter(setDetailsViewData),
discountsViewData,
updateDiscountsViewData: makeFieldUpdater(setDiscountsViewData),
resetDiscountsViewData: makeFieldResetter(setDiscountsViewData),
documentsViewData,
updateDocumentsViewData: makeFieldUpdater(setDocumentsViewData),
resetDocumentsViewData: makeFieldResetter(setDocumentsViewData),
fieldRepViewData,
updateFieldRepViewData: makeFieldUpdater(setFieldRepViewData),
resetFieldRepViewData: makeFieldResetter(setFieldRepViewData)
}
}
Basically I'd like an agnostic dispatcher?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
