我正在使用 React 和 Material ui,但我遇到了这个奇怪的错误。
我有一个父订单页面,然后将订单数组传递给订单组件,如下所示:
<PendingComponent
{...{pendingOrders}} />
然后在 PendingComponent 中我像这样映射订单数组:
<Box m="1rem 0 0 0">
{pendingOrders?.map((order, index) => (
<Accordion
key={index}
在这个手风琴内部,还有另一个组件,一个模态,我将订单作为道具传递给它,如下所示:
{updateSatus && (
<UpdateOrderStatusModal {...{ order }} />
)}
现在,当我尝试访问 UpdateOrderStatusModal 组件中的订单值时,发生了奇怪的事情,我没有得到我应该期望的映射订单值的正确值。
像这样,在 PendingComponent 组件中,我当前仅映射 3 个订单,然后将订单传递给 UpdateOrderStatusModal 组件,而不是获取单个订单,而是在我控制台日志时依次打印它们,并且我无法获取我想要进入 UpdateOrderStatusModal 的实际订单:
UpdateOrderStatusModal.jsx:27 The order in the modal {status: 'pending', userEmail: '[email protected]', dateCreated: 'Wed, August 16, 2023 at 6:14 PM', step: 0, orderProducts: {…}, …}
UpdateOrderStatusModal.jsx:27 The order in the modal {status: 'pending', userEmail: '[email protected]', dateCreated: 'Wed, August 16, 2023 at 6:14 PM', step: 0, orderProducts: {…}, …}
UpdateOrderStatusModal.jsx:27 The order in the modal {status: 'pending', userEmail: '[email protected]', dateCreated: 'Wed, August 16, 2023 at 5:15 PM', step: 0, orderProducts: {…}, …}
UpdateOrderStatusModal.jsx:27 The order in the modal {status: 'pending', userEmail: '[email protected]', dateCreated: 'Wed, August 16, 2023 at 5:15 PM', step: 0, orderProducts: {…}, …}
UpdateOrderStatusModal.jsx:27 The order in the modal {status: 'pending', userEmail: '[email protected]', dateCreated: 'Wed, August 16, 2023 at 5:08 PM', step: 0, orderProducts: {…}, …}
UpdateOrderStatusModal.jsx:27 The order in the modal {status: 'pending', userEmail: '[email protected]', dateCreated: 'Wed, August 16, 2023 at 5:08 PM', step: 0, orderProducts: {…}, …}
我违反了哪些 React 规则?为什么我会出现这种行为? 谢谢你。
更新 - 详细的可重现代码
我在不同的项目中重新创建了相同的问题并遇到了相同的问题。这是该组件的代码。
将一些项目添加到收藏夹后,我为用户提供了一个收藏夹产品页面:
<ul
role="list"
className="-my-6 divide-y divide-gray-200"
>
{products.map((product) => (
<li key={product.id} className="flex py-6">
<div
onClick={() => {
setOpenFavourites(false);
navigate(`/product/${product.id}`);
}}
className="hover:cursor-pointer h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200"
>
<img
src={product.images[0]}
alt={product.imageAlt}
className="h-full w-full object-cover object-center"
/>
</div>
<div className="ml-4 flex flex-1 flex-col">
<div>
<div className="flex justify-between text-base font-medium text-gray-900">
<h3>
<button
onClick={() => {
setOpenFavourites(false);
navigate(
`/product/${product.id}`
);
}}
>
{product.name}
</button>
</h3>
<p className="ml-4">
$ {product.price}
</p>
</div>
<p className="mt-1 text-sm text-gray-500">
{product.availability}
</p>
</div>
<div className="flex flex-1 items-end justify-between text-sm">
<p className="text-gray-500">
Min Order{" "}
<span className="text-gray-800">
{product.minOrder} Tonne
</span>
</p>
<div className="flex">
<button
type="button"
onClick={() =>
handleRemove(product.id)
}
className="font-medium text-primary hover:text-secondary"
>
Remove
</button>
</div>
<div className="flex">
<button
type="button"
onClick={() => setOpen(true)}
className="font-medium text-primary hover:text-secondary"
>
Open this Modal
</button>
</div>
{open && (<TestModal product={product} />)}
</div>
</div>
</li>
))}
</ul>
在上面的代码中,如果底部有测试按钮“打开此模态”及其下方的测试模态,则将映射的产品作为道具传递给它。
现在这是 TestModal 代码:
import React from 'react'
const TestModal = ({product}) => {
console.log("test modal mounted", product.name)
const investigate = () => {
console.log("investigate clicked", product.name, product.id)
}
return (
<>
<div className="justify-center items-center flex overflow-x-hidden overflow-y-auto fixed inset-0 z-50 outline-none focus:outline-none">
<div className="relative w-auto my-6 mx-auto max-w-3xl">
<div className="border-0 rounded-lg shadow-lg relative flex flex-col w-full bg-white outline-none focus:outline-none">
<div
className="
items-center justify-end p-6 border-t border-solid border-slate-200 rounded-b"
>
<button
className="text-red-500 background-transparent font-bold uppercase px-6 py-2 text-sm outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150"
type="button"
onClick={investigate}
>
Investigate
</button>
</div>
</div>
</div>
</div>
<div className="opacity-25 fixed inset-0 z-40 bg-black"></div>
</>
)
}
export default TestModal
现在在此模式上,假设我在 Potatoes 产品上单击了“打开此模式”,在测试模式中,当我单击“调查”按钮时,我希望将 Potato 产品信息控制台登录到该调查功能中,但这并没有发生,我打印了不同的产品信息,例如草莓,如果我将草莓作为我最喜欢的产品之一,喜欢它总是选择位于映射数组底部的产品,而不是那个我真的点击了。
我还注意到,当我使用模态(显示在其他组件之上的模态组件)时,会发生这种行为,当我使用没有某种 z 索引属性的组件时,它不会执行这种奇怪的行为。
我该如何解决这个问题?
我没有发现您的代码有任何问题(特别是因为信息有限......)。不过,按照你说的——
...当我控制台日志时,它们都被一个接一个地打印出来
假设您在开发环境中使用严格模式,这是完全正常的。在初始渲染期间重新渲染两次应该可以帮助您更快地找到错误,而 React 只在开发模式下这样做。
违反此规则的组件会出现不可预测的行为并导致错误。为了帮助您意外发现不纯的代码,严格模式会在开发过程中调用您的一些函数(仅那些应该是纯的函数)两次。