'How to return optional from useAppSelector / createSelector?
I have this selector in slice.ts:
export const authnResS = (state: RootState) => state.slice.authnRes
And this appSelector in hooks.ts:
export const authnRes = useAppSelector(authnResS)
When I bring cursor over authnRes it says type is const authnRes: AuthnRes but it can be null also. How can I mark it as it not always exist?
Maybe it is relating but when running yarn build I got this error:
> Build error occurred
TypeError: Cannot read property 'useContext' of null
at exports.useContext (/Users/kukodajanos/Workspace/Tikex/Portal/Team/node_modules/react/cjs/react.production.min.js:24:118)
at useReduxContext (/Users/kukodajanos/Workspace/Tikex/Portal/Team/node_modules/react-redux/lib/hooks/useReduxContext.js:27:46)
at useSelector (/Users/kukodajanos/Workspace/Tikex/Portal/Team/node_modules/react-redux/lib/hooks/useSelector.js:53:9)
slice.ts:
import { createSelector } from '@reduxjs/toolkit'
import axios from 'axios'
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
import {
AuthnRes,
UserDTO,
} from './Types'
import { useSelector } from 'react-redux'
import type { RootState } from './store'
interface StateType {
authnRes?: AuthnRes
}
const initialState: StateType = {
authnRes: null,
}
const namespace = 'slice'
export const me = createAsyncThunk(`${namespace}/me`, async () => {
const { data } = await axios({
method: 'get',
url: 'me',
headers: { crossDomain: true },
})
return data
})
const slice = createSlice({
name: 'slice',
initialState,
reducers: {
},
extraReducers: (builder) => {
.addCase(me.fulfilled, (state, { payload }) => {
state.authnRes = payload
})
},
})
If I replace in each component form this:
import { authnRes } from '../../../tikexModule/hooks'
to this:
import { useAppSelector } from '../../../tikexModule/hooks'
const authnRes = useAppSelector((state) => state.slice?.authnRes)
I got no error!! Why?
Solution 1:[1]
There's a type mismatch on your initialState. The authnRes is defined as AuthnRes or undefined but the initialState assign null to it. Try to change StateType to accept null. I created a TS playground that demonstrate it.
interface StateType {
authnRes?: AuthnRes
}
That said, the build error is caused by the use of useAppSelector outside a React component or custom hooks in your hooks.ts. You cannot export a variable with the return value of useAppSelector because it needs the Redux context which is not available on that scope. It's one of the rules of hooks. Probably fixing both this error your TypeScript compiler will understand the correct type of your state.
If you haven't done yet, I suggest you to install a linter, like ESLint and its relevant plugins like TS plugins and React Hooks plugin. Using it you'll see all these warnings while you are writing.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Mirco Bellagamba |
