Reputation: 1966
I have a redux-thunk reducer generated with createSlice
from redux-toolkit called getOne
.
getOne
fetches from an API and dispatches actions for the loading status, (startedLoading
, finishedLoading
, errorLoading
).
I would like to also call another actionCreater created in the same slice called insert
with the resulting data. or directly update the state from the getOne
reducer.
import { createSlice } from "@reduxjs/toolkit"
import { startedLoading, finishedLoading, errorLoading } from '../slices/loadingSlice'
const apiEndpoint = "/api/v1"
const fetchOptions = { headers: { "Content-Type": "application/json" } }
const createModelSlice = function (modelName) {
return createSlice({
name: modelName,
initialState: {byId: {}},
reducers: {
insert: (state, action) => {
// ...
},
getOne: (state, action) => async (dispatch) => {
// ...
try {
const response = await fetch(/* */)
// How would I update the store here?
// 1. reference the insert actionCreater somehow.
dispatch(insert({id: id, data: response))
// 2. construct the action manually
dispatch({action: `${modelName}/insert`, payload: {id: id, data: response))
// 3. Mutate the state here and rely immer. (I'm not sure exactly how that works)
state[modelName].byId[id] = response
dispatch(finishedLoading({ key: /* */ }))
} catch (error) {
dispatch(errorLoading({ key: /* */ }))
}
},
// ...
}
})
}
Upvotes: 2
Views: 2419
Reputation: 1966
I missed the part of docs about slices not being able to use thunk. either way, it wouldn't work as the thunk actions don't map to a reducer but rather dispatch other actions multiple other reducers/actions.
I added thunk actions to the slice actions after creating the slice. this way I can reference the other actions
import { createSlice } from "@reduxjs/toolkit"
const slice = createSlice({
name: name,
initialState: { byId: {} },
reducers: { /* */ }
}
slice.actions.myThunkAction = payload => async (dispatch, state) => {
// ...
slice.actions.nonThunkAction({ id: id, data: data})
slice.actions.anotherNonThunkAction({ index payload.index, data: data.map( /* */ )})
}
import { createSlice } from "@reduxjs/toolkit"
import { startedLoading, finishedLoading, errorLoading } from '../slices/loadingSlice'
import encodeURLParams from '../tools/encodeURLParams'
const apiEndpoint = "/api/v1"
const fetchOptions = { headers: { "Content-Type": "application/json" } }
const createModelSlice = function (modelName) {
const slice = createSlice({
name: modelName,
initialState: { byId: {} },
reducers: {
insert: (state, action) => {
// ...
},
bulkInsert: (state, action) => {
// ...
},
}
})
slice.actions.loadMany = payload => async (dispatch, state) => {
dispatch(startedLoading({ key: /* */ }))
try {
const response = await fetch(/* */)
dispatch(slice.actions.insert(response))
dispatch(finishedLoading({ key: /* */ }))
} catch (error) {
dispatch(errorLoading({ key: /* */ }))
}
}
slice.actions.loadOne = payload => async (dispatch, state) => {
dispatch(startedLoading({ key: /* */ }))
try {
const response = await fetch(/* */)
dispatch(slice.actions.bulkInsert(response))
dispatch(finishedLoading({ key: /* */ }))
} catch (error) {
dispatch(errorLoading({ key: /* */ }))
}
}
return slice
}
export default createModelSlice
Upvotes: 2