skip to Main Content

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


  1. 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. Since existingUser 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:

    f.id === parseInt(id)
    

    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 a useState. You can simply use the name and email you destructure from your existingUser[0] and they will render whenever you dispatch updates.

    Login or Signup to reply.
  2. Issue

    Route path params are always a string type, so if any f.id === id comparison fails but f.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:

    console.log('"5" === 5', "5" === 5); // false
    console.log('"5" == 5', "5" == 5);   // true

    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.

    console.log('"5" === String(5)', "5" === String(5)); // true
    console.log('"5" == String(5)', "5" == String(5));   // true
    console.log(
      '"12ab34cd56ef78-90" === Number("12ab34cd56ef78-90")',
      "12ab34cd56ef" === Number("12ab34cd56ef78-90")
    ); // false, 12ab34cd56ef78-90 <=> NaN

    I would suggest using Array.prototype.find instead, and provide a defined fallback object value to destructure values from.

    const { id } = useParams(); // String type
    
    const users = useSelector((state) => state.users);
    
    const existingUser = users.userList.find(f => String(f.id) === id); // Type-safe compare
    
    const { name, email } = existingUser ?? {}; // Fallback value to destructure from
    
    const [uname, setName] = useState(name ?? "");    // fallback value
    const [uemail, setEmail] = useState(email ?? ""); // fallback value
    

    You could also do much of this in the selector function.

    const { id } = useParams(); // String type
    
    const { name, email } = useSelector((state) => {
      return state.users.userList.find(f => String(f.id) === id) ?? {};
    });
    
    const [uname, setName] = useState(name ?? "");
    const [uemail, setEmail] = useState(email ?? "");
    

    Additionally, you should dispatch the updateUser action with the local state values that were updated.

    const handleUpdate = (event) => {
      event.preventDefault();
      dispatch(updateUser({
        id,
        name: uname,
        email: uemail
      }));
      navigate('/');
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search