Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

309
Views
React app throws TypeError: Cannot read properties of undefined (reading 'name') when compiling

I keep running into an issue with my CRUD application when I go to edit a name from my list, it throws an error "TypeError: Cannot read properties of undefined (reading 'name')".

It seems to stem from the "value={selectedUser.name}" in my input field, but when I remove it the app compiles but I cannot alter the field at all - nothing happens when you type. Any help is appreciated!

import React, { useState, useContext, useEffect } from 'react'
import { GlobalContext } from '../context/GlobalState'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { Form, FormGroup, Label, Input, Button } from 'reactstrap'

const EditUser = (props) => {
const [selectedUser, setSelectedUser] = useState({
  id: '',
  name: ''
});
const { users, editUser } = useContext(GlobalContext);
const navigate = useNavigate();
const currentUserId = useParams(props);

useEffect(() => {
  const userId = currentUserId;
  const selectedUser = users.find(user => user.id === userId)
  setSelectedUser(selectedUser)
}, [currentUserId, users])

const onSubmit = (e) => {
  e.preventDefault()
  editUser(selectedUser)
  navigate('/');
}

const onChange = (e) => {
  setSelectedUser({...selectedUser, [e.target.name]: e.target.value})
}

  return (
    <div>
        <Form onSubmit={onSubmit}>
            <FormGroup>
                <Label>Edit Name</Label>
                <Input type='text' name='name' value={selectedUser.name} onChange={onChange} placeholder='Enter Name'></Input>
            </FormGroup>
        <Button type='submit'>Edit Name</Button>
        <Link to='/' className='btn btn-danger m-2'>Back</Link>
        </Form>
    </div>
  )
}

export default EditUser
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

If currentUserId is undefined for any reason, or your users.find() returns undefined, then you're going to be storing undefined in your selectedUser state variable.

Given from your comments it looks like you're not able to use optional chaining (the foo?.bar syntax) then you probably just want to prevent this at source:

  useEffect(() => {
    const userId = currentUserId;
    const foundUser = users.find((user) => user.id === userId);
    if (foundUser) {
      setSelectedUser(foundUser);
    } 
  }, [currentUserId, users]);

Also note I renamed your variable inside your useEffect to avoid confusion with your selectedUser at the higher level.

about 4 years ago · Juan Pablo Isaza Report

0

Issue

Array.prototype.find returns the first matching element, or undefined if no such match is found.

const selectedUser = users.find(user => user.id === userId); // potentially undefined

Additionally, the returned value from the useParams hook is an object of the key-value pairs of any defined route path parameters. The code appears to incorrectly assume the returned value is the currentUserId parameter from a path, and uses that to search the users array.

const currentUserId = useParams(props);

useEffect(() => {
  const userId = currentUserId;
  const selectedUser = users.find(user => user.id === userId);
  setSelectedUser(selectedUser);
}, [currentUserId, users]);

I doubt there could ever be a found match comparing user.id against the returned params object.

Solution

I suspect that the actual path param is really userId. Either destructure it immediately from the useParams hook.

const { userId } = useParams();

or rename currentUserId to params and destructure userId in the hook.

const params = useParams(props);

useEffect(() => {
  const { userId } = params;
  const selectedUser = users.find(user => user.id === userId);
  setSelectedUser(selectedUser);
}, [params.userId, users]);

One last point about route params and id properties. The route params will always be a string type. Sometimes the id is actually a number type, so you'll want to use a type-safe equality check. Convert ids to string types, which covers both string ids and will convert numbers to number-like strings.

useEffect(() => {
  const { userId } = params;
  const selectedUser = users.find(user => String(user.id) === userId);
  setSelectedUser(selectedUser);
}, [params.userId, users]);

Guarding against null/undefined values.

  1. First, try to maintain a stable selectedUser state invariant. In other words, don't update it an undefined value unless you have a specific need to. Check the result of users.find to see if a match was found.

    const { userId } = useParams(props);
    
    useEffect(() => {
      const selectedUser = users.find(user => String(user.id) === userId);
      if (selectedUser) {
        setSelectedUser(selectedUser);
      }
    }, [userId, users]);
    
  2. Second, defensively guard against potentially null/undefined accesses in your render function, just in case. You can use the Optional Chaining and Nullish Coalescing Operators to guard null access and provide a valid defined value for the controlled input.

    <Input
      type='text'
      name='name'
      value={selectedUser?.name ?? ""}
      onChange={onChange}
      placeholder='Enter Name'
    />
    

    or if you prefer older-school null-checks/guard-clauses

    <Input
      type='text'
      name='name'
      value={(selectedUser && selectedUser.name) ?? ""}
      onChange={onChange}
      placeholder='Enter Name'
    />
    
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!