import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' import { AppState } from '../store' // declaring the types for our state export type CounterState = { value: number isLoading: boolean } const initialState: CounterState = { value: 0, isLoading: false, } // async thunks const url = '/api/counter' export const getCounterData = createAsyncThunk('counter/getCounterData', async () => { try { const res = await fetch(url) return await res.json() } catch (err) { return console.log(err) } }) // Redux Toolkit allows us to write "mutating" logic in reducers. // It doesn't actually mutate the state because it uses the Immer library, which detects changes to a "draft state" // and produces a brand new immutable state based off those changes export const counterSlice = createSlice({ name: 'counter', initialState, reducers: { increment: (state) => { state.value++ }, decrement: (state) => { state.value-- }, incrementByAmount: (state, action: PayloadAction) => { state.value += action.payload }, }, extraReducers: (builder) => { builder .addCase(getCounterData.pending, (state) => { state.isLoading = true }) .addCase(getCounterData.fulfilled, (state, action: PayloadAction<{ value: number }>) => { state.value = action.payload.value state.isLoading = false }) .addCase(getCounterData.rejected, (state) => { state.isLoading = false }) }, }) // actions export const { increment, decrement, incrementByAmount } = counterSlice.actions // selectors export const selectCount = (state: AppState) => state.counter.value export default counterSlice.reducer