I have an initial state like this.
const initialState = {
loading: false,
products: []
}
For the get products, I use thunk and I fetch datas from an API. loading field describes status of API call. If loading is true, i show progress in my component.
export const getProducts = createAsyncThunk('product/getProducts ',
async (payload, { rejectWithValue }) => {
try {
//fetch from somewhere
}
catch (e) {
return rejectWithValue(e.message)
}
}
)
const productSlice = createSlice({
name: "product",
initialState,
reducers: {
setLoading: (state, action) => {
state.loading = action.payload;
}
},
})
In a component first dispatch for loading and then getProducts.
// In some component
dispatch(setLoading(true))
dispatch(getProducts())
My question is, can I only call for getProducts and update loading state inside that function?
//In some component
dispatch(getProducts())
CodePudding user response:
Yes you can. This is very simple
Update your createSlice section like this
const productSlice = createSlice({
name: "product",
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(getProducts.pending, (state) => {
state.loading = true;
});
builder.addCase(getProducts.fulfilled, (state) => {
state.loading = false;
});
},
})
CodePudding user response:
You used createAsyncThunk and it is built in already to handle pending/fulfilled/rejected state with extraReducers
in createSlice.
You can also handle the rejected state if fetch fail.
const productSlice = createSlice({
name: 'product',
initialState,
extraReducers: (builder) => {
builder.addCase(getProducts.pending, (state, action) => {
state.isLoading = true;
})
builder.addCase(getProducts.fulfilled, (state, action) => {
state.isLoading = true;
state.products = action.payload
})
builder.addCase(getProducts.rejected, (state, action) => {
state.isLoading = false;
})
},
})
To use it, will be enough to simple call dispatch(getProducts()) and extraReducers with thunk take care of the rest.