-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b2830df
commit 71cd803
Showing
13 changed files
with
1,108 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit'; | ||
|
||
import counterReducer from '../features/counterSlice'; | ||
|
||
export function makeStore() { | ||
return configureStore({ | ||
reducer: { counter: counterReducer }, | ||
}); | ||
} | ||
|
||
const store = makeStore(); | ||
|
||
export type AppState = ReturnType<typeof store.getState>; | ||
|
||
export type AppDispatch = typeof store.dispatch; | ||
|
||
export type AppThunk<ReturnType = void> = ThunkAction< | ||
ReturnType, | ||
AppState, | ||
unknown, | ||
Action<string> | ||
>; | ||
|
||
export default store; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'; | ||
|
||
import type { AppState, AppThunk } from '../app/store'; | ||
|
||
export interface CounterState { | ||
value: number; | ||
status: 'idle' | 'loading' | 'failed'; | ||
} | ||
|
||
const initialState: CounterState = { | ||
value: 0, | ||
status: 'idle', | ||
}; | ||
|
||
// The function below is called a thunk and allows us to perform async logic. It | ||
// can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This | ||
// will call the thunk with the `dispatch` function as the first argument. Async | ||
// code can then be executed and other actions can be dispatched. Thunks are | ||
// typically used to make async requests. | ||
export const incrementAsync = createAsyncThunk( | ||
'counter/fetchCount', | ||
(amount: number) => { | ||
const response = { data: 1 }; | ||
// The value we return becomes the `fulfilled` action payload | ||
return response.data; | ||
} | ||
); | ||
|
||
export const counterSlice = createSlice({ | ||
name: 'counter', | ||
initialState, | ||
// The `reducers` field lets us define reducers and generate associated | ||
// actions | ||
reducers: { | ||
increment: (state) => { | ||
// 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 | ||
state.value += 1; | ||
}, | ||
decrement: (state) => { | ||
state.value -= 1; | ||
}, | ||
// Use the PayloadAction type to declare the contents of `action.payload` | ||
incrementByAmount: (state, action: PayloadAction<number>) => { | ||
state.value += action.payload; | ||
}, | ||
}, | ||
// The `extraReducers` field lets the slice handle actions defined elsewhere, | ||
// including actions generated by createAsyncThunk or in other slices. | ||
extraReducers: (builder) => { | ||
builder | ||
.addCase(incrementAsync.pending, (state) => { | ||
state.status = 'loading'; | ||
}) | ||
.addCase(incrementAsync.fulfilled, (state, action) => { | ||
state.status = 'idle'; | ||
state.value += action.payload; | ||
}); | ||
}, | ||
}); | ||
|
||
export const { increment, decrement, incrementByAmount } = counterSlice.actions; | ||
|
||
// The function below is called a selector and allows us to select a value from | ||
// the state. Selectors can also be defined inline where they're used instead of | ||
// in the slice file. For example: | ||
// `useSelector((state: RootState) => state.counter.value)` | ||
export const selectCount = (state: AppState) => state.counter.value; | ||
|
||
// We can also write thunks by hand, which may contain both sync and async | ||
// logic. Here's an example of conditionally dispatching actions based on | ||
// current state. | ||
export const incrementIfOdd = (amount: number): AppThunk => { | ||
return (dispatch, getState) => { | ||
const currentValue = selectCount(getState()); | ||
if (currentValue % 2 === 1) { | ||
dispatch(incrementByAmount(amount)); | ||
} | ||
}; | ||
}; | ||
|
||
export default counterSlice.reducer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.