子组件中不允许追加状态的setState错误类型



我最近在NextJS中切换到TypeScript(通过Create T3 App)。作为我的应用程序的一个组件,我想更新状态一旦Prisma突变。

我将setItems(通过useState初始化)传递给子组件,但是

仍然失败。
Type error: Argument of type '(prev: Example[]) => (Example | undefined)[]' is not assignable to parameter of type 'SetStateAction<Example[]>'.
我的代码如下:
interface FormProps {
setItems: Dispatch<SetStateAction<Example[]>>;
}
const Form: FC<FormProps> = ({ setItems }) => {
const [message, setMessage] = useState("");
//setItems([])
const { mutate: createExample } = api.example.createExample.useMutation({
onSuccess: (data) => {
setItems((prev) => [...prev, data]);
},
});
return (
<form
className="flex gap-2"
onSubmit={(event) => {
event.preventDefault();
createExample({
text: message,
});
setMessage("");
}}
>
<input
type="text"
placeholder="Your message..."
minLength={2}
maxLength={100}
value={message}
onChange={(event) => setMessage(event.target.value)}
/>
<button
type="submit"
className="rounded-md border-2 border-zinc-800 p-2 focus:outline-none"
>
Submit
</button>
</form>
);
};

在我的主页中初始化setItems:

const Demo: NextPage = () => {
const [items, setItems] = useState<Example[]>([]);
const { data: session, status } = useSession();
const user = api.example.getAll.useQuery(["getAll"], {
onSuccess: (user) => {
setItems(user.examples);
},
});
const { mutate: deleteExample } = api.example.deleteExample.useMutation({
onSuccess(example) {
setItems((prev) => prev.filter((item) => item.id !== example.id));
},
});
return (
<>
{session ? (
<>
<p>Hello {session ? session.user?.name : null}</p>
<button
type="button"
onClick={() => {
signOut().catch(console.log);
}}
>
Logout
</button>
<br />
<ul>
{user.data
? items.map((example) => (
<li>
{example.text}{" "}
<button
onClick={() => {
deleteExample({ id: example.id });
}}
>
X
</button>
</li>
))
: null}
</ul>
<br />
<Form setItems={setItems} />
</>
) : (
<button
type="button"
onClick={() => {
signIn("email").catch(console.log);
}}
>
Login with Email
</button>
)}
</>
);
};

它似乎得到了正确的类型,知道它是一个' Example '。但是,抛出类型错误,因为我试图访问前一个状态。

如何在保持类型一致的情况下组合状态?

我认为问题是onSuccess方法中的data变量可能是undefined

并且typescript不希望将一个可能未定义的数组赋值给另一个未定义的数组

现在,我们如何解决这个问题?这得看情况。

为什么dataundefined?有三种可能:

  1. data总是未定义的(所以如果你把鼠标悬停在数据上,你应该看到data: undefined)。

如果是这种情况,你要么有一些其他的bug导致data是未定义的,或者你期望有一个未定义的列表,如果你这样做,通过将useState<Example[]>更改为useState<(Example|undefined)[]>Dispatch<SetStateAction<Example[]>>更改为Dispatch<SetStateAction<(Example|undefined)[]>>来告诉typescript是这种情况。

  1. data有时未定义(data: Example|undefined)。

如果Data有时未定义,则还有两种可能。或者您想要将undefined添加到列表中,或者您想要避免将undefined添加到列表中。

如果你想在列表中添加undefined,请按照上一步操作。

如果您不想将undefined添加到列表中,只需在运行setItems函数之前确保它不是undefined:

onSuccess: (data) => {
if (data)
setItems((prev) => [...prev, data]);
},

如果在此之后你仍然收到错误,做以下更改:[...prev, data as Example]

  1. 数据从不是未定义的。

如果你知道data永远不会被定义,但它仍然被定义,并且没有办法改变这个事实,你可以使用前一种情况的代码告诉typescript:

setItems((prev) => [...prev, data as Example]);

上述情况之一应能解决问题。

最新更新