I am new to typescript with react and tried so many thing but doesn't work. state doesn't work and getting typescript error Property 'state and dispatch' does not exist on type 'UserContextType | null' UserContRed.tsx
export const UserContRed = () => {
//const context = useContext(ContRedContext)
const {state , dispatch } = useContext(ContRedContext)
const [firstname, setFirstname] = useState('')
const [id, setId ] = useState(0)
const [lastname, setLastname] = useState('')
// let displayUsers = context?.state.users.map( (u:any) => {
let displayUsers = state.users.map( (u:any) => {
return(
<ul key={u.id}>
<li>{u.id}</li>
<li>{u.firstname}</li>
<li>{u.lastname}</li>
</ul>
)
})
const addUser = () => {
const addUser = () => dispatch({type:ActionType.ADD, payload : {id:1,firstname:firstname, lastname:lastname}})
}
return(
<div>
<div>
<label>Id: </label>
<input type="text" onChange={(e)=>{setId(Number(e.target.value))}} />
</div>
<div>
<label>Firstname: </label>
<input type="text" onChange={(e)=>{setFirstname(e.target.value)}} />
</div>
<div>
<label>Lastname: </label>
<input type="text" onChange={(e)=>{setLastname(e.target.value)}} />
</div>
<button onClick={addUser}>sendToStore</button>
</div>
)
}
ContRed.tsx
export type User = {
id: number;
firstname: string;
lastname: string;
}
type contredProps = {
children: React.ReactNode
}
export type IuserState = {
users : User[]
}
const initialState: IuserState = {
users : [
{
id:0,
firstname:'',
lastname: ''
}
]
}
export enum ActionType {
ADD="add",
REMOVE="remove"
}
type userAction = {
type: ActionType,
payload: User
}
export const reducer = (state: IuserState, action: userAction) : typeof initialState => {
switch(action.type){
case "add":
return ({...state, users: [...state.users,
{id:action.payload.id,
firstname:action.payload.firstname,
lastname:action.payload.lastname
}
]
})
case "remove":
return ({...state, users: [
...state.users.filter(data => data.id !== action.payload.id)]
})
default:
return state;
}
}
type UserContextType = {
state: IuserState
dispatch: React.Dispatch<userAction>
}
export const ContRedContext = createContext<UserContextType|null>({
state:initialState,
dispatch: () => {}
})
export const ContRedContextProvier = ({children}:contredProps) => {
const[state,dispatch] = useReducer(reducer,initialState as IuserState);
const value : UserContextType = { state, dispatch}
return(
<ContRedContext.Provider value={value}>
{children}
</ContRedContext.Provider>
)
}
App.tsx
<ContRedContextProvier>
<UserContRed/>
</ContRedContextProvier>
I tried with using constant instead de-structuring typescript error goes away but it doesn't add or doesn't update the state. typescript is so hard seems to me with react please explain or guide what i am doing wrong. Below tried typescript is fine but functionality doesn't work
const context = useContext(ContRedContext)
let displayUsers = context?.state.users.map( (u:any) => { ...}
const addUser = () => context?.state.dispatch({type:ActionType.ADD, payload : {id:1,firstname:firstname, lastname:lastname}})
Tried:
const context = useContext(ContRedContext)
let displayUsers = context?.state.users.map( (u:any) => { ...}
const addUser = () => context?.state.dispatch({type:ActionType.ADD, payload : {id:1,firstname:firstname, lastname:lastname}})
Expected: User should add to state and render in child component.
You have typed the ContRedContext
to be nullable, e.g. createContext<UserContextType | null>({ .... })
, so consumers would need to use a null-check prior to accessing state
or dispatch
.
Example:
const context = useContext(ContRedContext);
if (!context) return null;
const { state, dispatch } = context; // not null 🙂
But you don't appear to ever pass a null
context value, even for the default context value, and likely have no need to.
Update the ContRedContext
context type declaration to remove the null
type:
export const ContRedContext = createContext<UserContextType>({
state: initialState,
dispatch: () => {}
});
There is an additional issue in the UserContRed
component with the addUser
handler. It declares a function that issues the dispatch and never calls it.
Issue code:
const addUser = () => {
const addUser = () => // <-- never called
dispatch({
type: ActionType.ADD,
payload: { id, firstname: firstname, lastname: lastname }
});
};
Update to just call dispatch
:
const addUser = () => {
dispatch({
type: ActionType.ADD,
payload: { id, firstname, lastname }
});
};