React Typescript - 类型的参数不能分配给类型 'SetStateAction<User | Record<string, never>>' 的参数



我有一个简单的React web应用程序的数据(对象列表)的用户,待办事项和帖子,在那里我显示,更新和删除数据。

我有一个名为UserView的组件,我从道具中获取用户数据,然后我用useEffect保存状态下的数据

interface UserViewProps {
userData: User;
}
export default function UserView({
userData,
...
}: UserViewProps) {
const [user, setUser] = useState<User | Record<string, never>>({});
useEffect(() => {
...
setUser({ ...userData });
}, [todosData]);

问题是当我想改变用户状态从输入传递到一个回调函数与解构:

<input
onChange={(e) =>
setUser({
...user,
name: e.target.value,
})
}

我收到以下TypeScript错误:

Argument of type '{ name: string; id: number; username: string; email: string; address: Address; phone: string; website: string; company: Company; } | { name: string; }' is not assignable to parameter of type 'SetStateAction<User | Record<string, never>>'.
Type '{ name: string; }' is not assignable to type 'SetStateAction<User | Record<string, never>>'.
Type '{ name: string; }' is not assignable to type 'Record<string, never>'.
Property 'name' is incompatible with index signature.
Type 'string' is not assignable to type 'never'.ts(2345)

当我改变

const [user, setUser] = useState<User | Record<string, never>>({});

const [user, setUser] = useState<User | any>({});

一切正常如何修复这个TypeScript错误?

完整代码如下:

import React, { useEffect, useState } from 'react';
import { Post, Todo, User } from '../../../helpers/utils';
import { StyledUserView } from './style';
interface UserViewProps {
userData: User;
todosData: Todo[];
postsData: Post[];
handleUserDelete: (userId: number) => void;
handleUserUpdate: (updatedUser: User) => void;
}
export default function UserView({
userData,
todosData,
postsData,
handleUserDelete,
handleUserUpdate,
}: UserViewProps) {
const [isUncompletedTodo, setIsUncompletedTodo] = useState(false);
const [isShowOtherData, setIsShowOtherData] = useState(false);
const [user, setUser] = useState<User | any>({});
useEffect(() => {
if (todosData.find((todo) => todo.completed === false)) {
setIsUncompletedTodo(true);
} else {
setIsUncompletedTodo(false);
}
setUser({ ...userData });
}, [todosData]);
return (
<StyledUserView isUncompletedTodo={isUncompletedTodo}>
ID: {user.id} <br />
<label htmlFor={`${user.id}-name-input`}>Name:</label>{' '}
<input
onChange={(e) =>
setUser({
...user,
name: e.target.value,
})
}
id={`${user.id}-name-input`}
type="text"
value={user.name}
/>{' '}
<br />
<label htmlFor={`${user.id}-email-input`}>Email:</label>{' '}
<input
onChange={(e) =>
setUser({
...user,
email: e.target.value,
})
}
id={`${user.id}-email-input`}
type="text"
value={user.email}
/>{' '}
<br />
{isShowOtherData && (
<section className="other-data">
<label htmlFor={`${user.id}-street-input`}>Street:</label>{' '}
<input
onChange={(e) =>
setUser({
...user,
address: {
...user.address,
street: e.target.value,
},
})
}
id={`${user.id}-street-input`}
type="text"
value={user.address.street}
/>{' '}
<br />
<label htmlFor={`${user.id}-city-input`}>City:</label>{' '}
<input
id={`${user.id}-city-input`}
type="text"
value={user.address.city}
onChange={(e) =>
setUser({
...user,
address: {
...user.address,
city: e.target.value,
},
})
}
/>{' '}
<br />
<label htmlFor={`${user.id}-zip-code-input`}>Zip Code:</label>{' '}
<input
id={`${user.id}-zip-code-input`}
type="text"
value={user.address.zipcode}
onChange={(e) =>
setUser({
...user,
address: {
...user.address,
zipcode: e.target.value,
},
})
}
/>{' '}
<br />
</section>
)}
<button
onClick={() => {
setIsShowOtherData(!isShowOtherData);
}}
>
{isShowOtherData ? 'Hide Other Data' : 'Show Other Data'}
</button>
<button onClick={() => handleUserUpdate(user)}>Update</button>
<button
onClick={() => {
handleUserDelete(user.id);
}}
>
Delete
</button>
</StyledUserView>
);
}

您可以尝试更改

const [user, setUser] = useState<User | Record<string, never>>({});
// to 
const [user, setUser] = useState<User | Record<string, any>>({});
//or 
const [user, setUser] = useState<User | Record<string, string>>({});

添加初始用户名为空字符串

const [user, setUser] = useState<{ name: string }>({
name: ""
});

代码sanbox

如果名称是一个变量,则需要输入[name];否则它是静态的,则使用"name">

<input
onChange={(e) =>
setUser(prv=>{
...prv,
[name]: e.target.value,
})
}

最新更新