React app throws TypeError: Cannot read properties of undefined (reading 'name') when compiling
React app throws TypeError: Cannot read properties of undefined (reading 'name') when compiling
当我从列表中编辑名称时,我的 CRUD 应用程序一直 运行 出现问题,它抛出错误“TypeError:无法读取未定义的属性(读取 'name') ".
它似乎源于我输入字段中的“值={selectedUser.name}”,但是当我删除它时,应用程序编译但我根本无法更改该字段 - 输入时没有任何反应。感谢您的帮助!
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
如果 currentUserId
出于任何原因是 undefined
,或者您的 users.find()
returns undefined
,那么您将存储 undefined
在你的 selectedUser
状态变量中。
根据您的评论,您似乎无法使用 optional chaining(foo?.bar
语法),那么您可能只想从源头上防止这种情况发生:
useEffect(() => {
const userId = currentUserId;
const foundUser = users.find((user) => user.id === userId);
if (foundUser) {
setSelectedUser(foundUser);
}
}, [currentUserId, users]);
另请注意,我在您的 useEffect
中重命名了您的变量,以避免与更高级别的 selectedUser
混淆。
问题
Array.prototype.find
returns 第一个匹配元素,或者 undefined 如果没有找到这样的匹配。
const selectedUser = users.find(user => user.id === userId); // potentially undefined
此外,useParams
钩子的返回值是 key-value 对任何已定义路由路径参数的对象。该代码似乎错误地假定返回值 是 来自路径的 currentUserId
参数,并使用它来搜索 users
数组。
const currentUserId = useParams(props);
useEffect(() => {
const userId = currentUserId;
const selectedUser = users.find(user => user.id === userId);
setSelectedUser(selectedUser);
}, [currentUserId, users]);
我怀疑 曾经 是否会找到匹配 user.id
与返回的参数对象进行比较。
解决方案
我怀疑 actual 路径参数真的是 userId
。要么立即从 useParams
挂钩中解构它。
const { userId } = useParams();
或重命名currentUserId
为params
并在钩子中解构userId
const params = useParams(props);
useEffect(() => {
const { userId } = params;
const selectedUser = users.find(user => user.id === userId);
setSelectedUser(selectedUser);
}, [params.userId, users]);
关于路由参数和 id 属性的最后一点。路由参数将 always 是字符串类型。有时 id
实际上是一个数字类型,因此您需要使用 type-safe 相等性检查。 Convert ids to string types,涵盖了字符串id,将数字转换为number-like字符串。
useEffect(() => {
const { userId } = params;
const selectedUser = users.find(user => String(user.id) === userId);
setSelectedUser(selectedUser);
}, [params.userId, users]);
防范 null/undefined 价值观。
首先,尽量保持稳定的selectedUser
状态不变。换句话说,除非您有特定需要,否则不要将其更新为未定义的值。检查 users.find
的结果以查看是否找到匹配项。
const { userId } = useParams(props);
useEffect(() => {
const selectedUser = users.find(user => String(user.id) === userId);
if (selectedUser) {
setSelectedUser(selectedUser);
}
}, [userId, users]);
其次,以防万一,防御性地防止渲染函数中的潜在 null/undefined 访问。您可以使用可选链接和空值合并运算符来保护空访问并为受控输入提供有效的定义值。
<Input
type='text'
name='name'
value={selectedUser?.name ?? ""}
onChange={onChange}
placeholder='Enter Name'
/>
或者如果你喜欢 older-school null-checks/guard-clauses
<Input
type='text'
name='name'
value={(selectedUser && selectedUser.name) ?? ""}
onChange={onChange}
placeholder='Enter Name'
/>
当我从列表中编辑名称时,我的 CRUD 应用程序一直 运行 出现问题,它抛出错误“TypeError:无法读取未定义的属性(读取 'name') ".
它似乎源于我输入字段中的“值={selectedUser.name}”,但是当我删除它时,应用程序编译但我根本无法更改该字段 - 输入时没有任何反应。感谢您的帮助!
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
如果 currentUserId
出于任何原因是 undefined
,或者您的 users.find()
returns undefined
,那么您将存储 undefined
在你的 selectedUser
状态变量中。
根据您的评论,您似乎无法使用 optional chaining(foo?.bar
语法),那么您可能只想从源头上防止这种情况发生:
useEffect(() => {
const userId = currentUserId;
const foundUser = users.find((user) => user.id === userId);
if (foundUser) {
setSelectedUser(foundUser);
}
}, [currentUserId, users]);
另请注意,我在您的 useEffect
中重命名了您的变量,以避免与更高级别的 selectedUser
混淆。
问题
Array.prototype.find
returns 第一个匹配元素,或者 undefined 如果没有找到这样的匹配。
const selectedUser = users.find(user => user.id === userId); // potentially undefined
此外,useParams
钩子的返回值是 key-value 对任何已定义路由路径参数的对象。该代码似乎错误地假定返回值 是 来自路径的 currentUserId
参数,并使用它来搜索 users
数组。
const currentUserId = useParams(props);
useEffect(() => {
const userId = currentUserId;
const selectedUser = users.find(user => user.id === userId);
setSelectedUser(selectedUser);
}, [currentUserId, users]);
我怀疑 曾经 是否会找到匹配 user.id
与返回的参数对象进行比较。
解决方案
我怀疑 actual 路径参数真的是 userId
。要么立即从 useParams
挂钩中解构它。
const { userId } = useParams();
或重命名currentUserId
为params
并在钩子中解构userId
const params = useParams(props);
useEffect(() => {
const { userId } = params;
const selectedUser = users.find(user => user.id === userId);
setSelectedUser(selectedUser);
}, [params.userId, users]);
关于路由参数和 id 属性的最后一点。路由参数将 always 是字符串类型。有时 id
实际上是一个数字类型,因此您需要使用 type-safe 相等性检查。 Convert ids to string types,涵盖了字符串id,将数字转换为number-like字符串。
useEffect(() => {
const { userId } = params;
const selectedUser = users.find(user => String(user.id) === userId);
setSelectedUser(selectedUser);
}, [params.userId, users]);
防范 null/undefined 价值观。
首先,尽量保持稳定的
selectedUser
状态不变。换句话说,除非您有特定需要,否则不要将其更新为未定义的值。检查users.find
的结果以查看是否找到匹配项。const { userId } = useParams(props); useEffect(() => { const selectedUser = users.find(user => String(user.id) === userId); if (selectedUser) { setSelectedUser(selectedUser); } }, [userId, users]);
其次,以防万一,防御性地防止渲染函数中的潜在 null/undefined 访问。您可以使用可选链接和空值合并运算符来保护空访问并为受控输入提供有效的定义值。
<Input type='text' name='name' value={selectedUser?.name ?? ""} onChange={onChange} placeholder='Enter Name' />
或者如果你喜欢 older-school null-checks/guard-clauses
<Input type='text' name='name' value={(selectedUser && selectedUser.name) ?? ""} onChange={onChange} placeholder='Enter Name' />