I want to update the user data. I’m getting existing user data successfully but it’s not updating. Above error is showing.
When i remove one equal sign from the below line then error removed but still user data not updating.
const existingUser = users.userList.filter(f => f.id == id);
import React, { useState } from 'react'
import { useSelector, useDispatch } from 'react-redux';
import { useNavigate, useParams } from 'react-router-dom';
import { updateUser } from '../redux/slice/userReducer';
const Update = () => {
const { id } = useParams();
//console.log(id)
const users = useSelector((state) => state.users);
const existingUser = users.userList.filter(f => f.id === id);
//console.log(existingUser);
const { name, email } = existingUser[0];
const [uname, setName] = useState(name);
const [uemail, setEmail] = useState(email);
const dispatch = useDispatch();
const navigate = useNavigate();
const handleUpdate = (event) => {
event.preventDefault();
dispatch(updateUser({
id: id,
name: name,
email: email
}));
navigate('/');
}
return (
<div className='d-flex w-100 vh-100 justify-content-center align-items-center'>
<div className='w-50 border bg-secondary text-white p-5'>
<h3>Update User</h3>
<form onSubmit={handleUpdate}>
<div>
<label htmlFor='name'>Name:</label>
<input
type='text'
name='name'
className='form-control'
placeholder='enter name'
value={uname}
onChange={e => setName(e.target.value)}
/>
</div>
<div>
<label htmlFor='name'>Email:</label>
<input
type='email'
name='email'
className='form-control'
placeholder='enter email'
value={uemail}
onChange={e => setEmail(e.target.value)}
/>
</div>
<br />
<button className='btn btn-info'>Update</button>
</form>
</div>
</div>
)
}
export default Update
2
Answers
I’m not sure what your data structure is, but from the provided codes I can explain and guess what the problem is.
The error you get means that the 0th element of your
existingUser
doesn’t exist. SinceexistingUser
is coming from a filter and filter returns an array, we can assume that the condition inside the filter isn’t meet for any of the elements.When you said that changing
===
to==
causes it to be working, we can guess that f.id and id aren’t of the same type. Maybe one is a string and the other is an integer.Using == has actually solved your initial problem. But if you want to use === you can try changing the values’ types. For example if id is a string and f.id is an integer, you can write the condition like this:
You can learn about their differences by searching Google.
Your next issue is that after the above error is fixed the data isn’t updated. This is because of the design pattern you have used in your component. A useState only takes one initial value and doesn’t change throughout component lifecycle unless you update it using
setState
.Since you’re using useSelector and dispatch, I assume you’re using
redux
. In this case I don’t see the need for auseState
. You can simply use thename
andemail
you destructure from yourexistingUser[0]
and they will render whenever youdispatch updates
.Issue
Route path params are always a string type, so if any
f.id === id
comparison fails butf.id == id
works then this indicates a type mismatch between operands. When using strict equality===
then the values being compared need to be of the same type. Loose equality==
checks will do attempt a type conversion prior to comparison.Consider the following:
See Equality comparisons and sameness for more details.
The
Array.prototype.filter
also potentially returns an empty array if no elements in the source array pass the filtering predicate, so the code should not assume a populated array with elements to destructure properties from.Solution
The code should apply a type-safe comparison. I suggest using string comparison so both strings and number-like strings can be compared. Trying to convert non-numeric strings to numbers doesn’t always work.
I would suggest using
Array.prototype.find
instead, and provide a defined fallback object value to destructure values from.You could also do much of this in the selector function.
Additionally, you should dispatch the
updateUser
action with the local state values that were updated.