# Redux alignement
The goal of this meeting is to present how I've implemented Redux with the CaseCreationV2 feature. Before reading this documentation, which is about our project, please make sure to read this: [Redux - Usage with typescript](https://redux-toolkit.js.org/usage/usage-with-typescript#introduction)
## Structure
```
store/
- features/
- caseInit/
- initialState.ts
- caseInitSlice.ts
- selectors.ts
- thunks.ts
- arch/
- stepBar/
- selectors.ts
- thunks.ts
- types/
- hooks.ts
- store.ts
```
### `store`
The whole state of the app (here, feature)
```
export const store = configureStore<RootState>({
reducer: {
stepBar: stepBarSlice.reducer,
caseInit: caseInitSlice.reducer,
maxilla: maxillaSlice.reducer,
mandible: mandibleSlice.reducer,
},
})
```
### `initialState`
useful to compare changes, or reset data without reloading the whole page
### `<feature>Slice`
contains the reducers of the feature:
```
export const caseInitSlice = createSlice({
name: "caseInit",
initialState: initialState,
reducers: {
changePatientFirstName: (state, action: PayloadAction<string>) => {
state.patient.firstName = action.payload
if (state.dataChecked) {
checkFirstName(state)
}
},
// ...
},
extraReducers(builder) {
builder
.addCase(createCaseDraft.pending, (state) => {
state.creatDraftStatus = "loading"
})
.addCase(createCaseDraft.fulfilled, (state, action) => {
state.creatDraftStatus = "succeeded"
state.draftId = action.payload.id
const newPatient = {
birthDate: action.payload.patient.birthDate,
firstName: action.payload.patient.firstName,
lastName: action.payload.patient.lastName,
middleName: action.payload.patient?.middleName ?? "-",
gender: action.payload.patient.gender,
customPatientId: action.payload.customPatientId,
patientId: action.payload.patientId,
}
state.patient = newPatient
state.patientInit = newPatient
state.caseOwnerB2cUserId = action.payload.caseOwnerB2cUserId
state.caseOwnerB2cUserIdInit = action.payload.caseOwnerB2cUserId
state.caseType = action.payload.caseType
state.caseTypeInit = action.payload.caseType
})
.addCase(createCaseDraft.rejected, (state, action) => {
state.creatDraftStatus = "failed"
state.errors.createCaseDraft = action.payload
})
// ...
},
})
```
the actions creators are then exported from the slice (at the end of the file):
```
export const {
changePatientFirstName,
// ...
} = caseInitSlice.actions
// In another file ------
const dispatch = useAppDispatch()
dispach(changePatientFirstName(patientFirstName))
```
this generates the following action: `{type: "caseInit/changePatientFirstName", payload: patientFirstName}`
### `selectors`
A selector is a function that takes the state as parameter and returns a part of the state or a computation of the state
- part of the state: arrow function ie `
const selectCaseInit = (state) => state.caseInit
`
- computation of the state: use the `createSelector` function, it memoizes the result of the computation
```
const selectIsGettingDraft = createSelector(
[selectCaseInit],
(caseInit) => caseInit.getDraftStatus === "loading")
```
, see https://redux-toolkit.js.org/api/createSelector
### `thunks`
A thunk
## Behaviour
### Immutability
`createSlice()` uses immer, which means it simplifies a lot how we change the state, see https://redux-toolkit.js.org/usage/immer-reducers.
Example of what we can avoid thanks to it:
```
function handwrittenReducer(state, action) {
return {
...state,
first: {
...state.first,
second: {
...state.first.second,
[action.someId]: {
...state.first.second[action.someId],
fourth: action.someValue,
},
},
},
}
}
```
would become
```
function handwrittenReducer(state, action) {
state.first.second[action.someId].fourth = action.someValue
}
```
:+1: