I am writing crud operations for my mern-stack using redux-toolkit. I want to prefill input fields with the data from the database. All that code works. I have the data in my input fields. But I am stopped by typescript, because TypeScript says:
The property X does not exist for the User[] type.
So how can I tell TypeScript that user has this properties? I tried it with exclamation marks and import the interface User into the userdisplay for setting user:User, but nothing helps.
The code in React:
const UserDisplay = () => {
//bringing in the user
const dispatch = useAppDispatch();
const selector = useAppSelector((state:RootState)=>state.user);
const {user, isError, isLoading, message} = selector;
const {id} = useParams();
useEffect(()=>{
if(isError){
toast.error(message);
}
dispatch(getUser(id!));
return ()=>{
dispatch(reset())
}
}, [dispatch, isError, message, id]);
//set Variables for input fields
const [formdata, setFormdata] = useState<{vorname:string,
nachname:string, username:string, email:string, street:string,
number:string,plz:string, city:string, isAdmin:boolean,
createdAt:string}>({
vorname:"",
nachname:"",
username:"",
email:"",
street:"",
number:"",
plz:"",
city:"",
isAdmin:false,
createdAt:Date.toLocaleString(),
})
console.log(user);
const {vorname, nachname, username, email, street, number, plz, city, isAdmin, createdAt} = formdata;
//overgive data from db to input fields
useEffect(()=>{
if(user){
setFormdata({
vorname:user.vorname, //here is every value underlined, property not exist
nachname:user.nachname,
username:user.username,
email:user.email,
street:user.street,
number: user.number,
plz:user.plz,
city:user.city,
isAdmin:user.isAdmin,
createdAt:user.createdAt,
})
}
}, [user])
That are the parts out of the slice:
interface User{
_id?:string,
id?:string,
vorname:string
nachname:string
username:string
email:string
street:string
number:string
plz:string
city:string
password:string
isAdmin:boolean
createdAt: Date
accessToken: string;
}
interface InitialState{
user:User[],
isLoading:boolean,
isSuccess:boolean,
isError:boolean,
message:string,
}
const initialState:InitialState ={
user:[],
isLoading:false,
isSuccess:false,
isError:false,
message:"",
}
type AsyncThunkConfig = {
state: RootState
}
//this function works - I get the user in my userDisplay
export const getUser = createAsyncThunk<User[], string, AsyncThunkConfig>('/user/find', async (Id:string, thunkAPI)=>{
try{
const token = thunkAPI.getState().auth.user!.accessToken;
return await userService.getUser(Id, token);
}catch (error:any) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString()
return thunkAPI.rejectWithValue(message as string)
}
})
Slice:
export const userSlice = createSlice({
name: 'user',
initialState,
reducers:{
reset:(state)=>{
state.isLoading = false;
state.isSuccess = false;
state.isError = false;
state.message = "";
}
},
extraReducers(builder) {
builder
.addCase(updateUser.pending, (state)=>{
state.isLoading = true;
})
.addCase(updateUser.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.user.push(action.payload)
})
.addCase(updateUser.rejected, (state, action:any)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(deleteUser.pending, (state)=>{
state.isLoading = true;
})
.addCase(deleteUser.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.user.filter((item)=>item._id !== action.payload.id)
})
.addCase(deleteUser.rejected, (state, action:any)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(getUser.pending, (state)=>{
state.isLoading = true;
})
.addCase(getUser.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.user = action.payload; //that is underlined when I only use User or say object
})