在 React 打字稿中动态呈现元素时的意外状态行为
Unexpected state behaviour while dynamically rendering elements in React typescript
我将这些元素放在一个数组中,在 .map()
中动态呈现。
我尝试将它们传递到在模态内呈现的表单组件中,但出于某种原因,我传递到表单组件中的状态变得混乱。
<Row>
{fens?.map(
(
fen: {
_id: string;
fen: string;
description: string;
san: string;
},
index: number
) => (
<Col>
<Card title={fen.fen}>
[..stuff..]
{isLogged && (
<>
<p>
<strong>Description:</strong>
{fen.description}
</p>
<p>
<strong>Correct move:</strong>
{fen.san}
</p>
<Button
onClick={() => {
setIndex(index);
//setFen(fen.fen);
//setSan(fen.san);
setIsEditPositionModalVisible(true);
}}
>
<strong>Edit Position</strong> <EditOutlined />
</Button>
<Modal
title="Edit Position"
visible={isEditPositionModalVisible}
onOk={() => setIsEditPositionModalVisible(false)}
onCancel={() => setIsEditPositionModalVisible(false)}
>
{/* formcomponent */}
<FormComponent
description={fen.description}
index={_index}
fen={fen.fen}
san={fen.san}
setFens={setFens}
password={pass}
id={fenId as string}
type={"edit"}
setIsModalVisible={setIsEditPositionModalVisible}
/>
</Modal>
</>
)}
</p>
</Card>
</Col>
)
)}
</Row>
FormComponent 中的代码:
return (
[...]
<Form.Item
name="fen"
label="Fen"
tooltip="add a valid position in Forsyth-Edwards Notation"
initialValue={props.fen}
</Form.Item>
[...]
);
代码的亮点是我在 FormComponent 内部传递数据,并使用它来设置 initialValue。 Form 组件内的所有字段都被初始化为数组的最后一个元素。我尝试根据索引在 onClick 上设置字段,起初它们被正确初始化,但是当我尝试关闭模式并打开另一个模式时,值保持不变..
我正在使用 antd 进行样式设置,但我认为这不相关。
编辑:我刚刚注意到一个奇怪的行为,这有点道理:通过仅使用一个状态变量(即 isEditPositionModalVisible
),我可能会打开所有一次模态和最后呈现的模态在逻辑上是数组中的最后一个。也许这是正确的轨道,但我想不出一种方法来诚实地管理动态呈现的模态。
Edit2:我想我找到了问题,但没有找到解决方案。我将初始值传递给 as 道具,因为我只使用模态的单个实例,所以呈现的值不会改变。我不知道这是否是一个 antd 问题,但显然
中的 initialValues 未同步。希望有人知道如何动态更改它们。
Edit3:好的,也许我找到了解决方案,但通过谷歌搜索我找不到任何有用的东西:有没有办法人为地卸载功能组件?这个想法基本上是在模态不显示时销毁组件,并在显示时安装它。它可能会解决所有问题。
Edit4 根据此处的要求,我的代码有一个沙箱:
https://codesandbox.io/embed/react-typescript-forked-j9p17h?fontsize=14&hidenavigation=1&theme=dark
重要的部分在最后,当我穿过沼泽地时。您可以立即注意到,当第二次使用“编辑位置”按钮打开模态时,该特定模态内的表单的 InitialValues 不会改变。
您已经在使用 Antd 表单。您可以使用 antd 表单挂钩来设置、重置和获取值。您不需要将每个 属性 传递给 FormComponent
.
- 首先像这样创建一个 antd 钩子:
const [form] = Form.useForm();
- 当您点击“编辑位置”按钮时,您已经有该特定卡片的
fen
记录,只需使用 form.setFieldsValues({...})
设置表单值,如下所示:
<Button
onClick={() => {
form.setFieldsValue(fen);
setIndex(index);
setIsEditPositionModalVisible(true);
}}
>
<strong>Edit Position</strong> <EditOutlined />
</Button>
- 将
form
属性传递给 FormComponent。
- 在您的
PropsInterface
中添加 form: FormInstance;
- 将表单 Prop 传递给 antd 表单
<Form form={form}> </Form>
您不需要在 Form.Item
中使用 initialValue。由于您已经使用 form.setFieldsValue().
设置了值
当您点击 Add Position
时,只需使用 form.resetFields()
重置表格即可。
希望这能解决您的问题。
请关注antd Form API.
我将这些元素放在一个数组中,在 .map()
中动态呈现。
我尝试将它们传递到在模态内呈现的表单组件中,但出于某种原因,我传递到表单组件中的状态变得混乱。
<Row>
{fens?.map(
(
fen: {
_id: string;
fen: string;
description: string;
san: string;
},
index: number
) => (
<Col>
<Card title={fen.fen}>
[..stuff..]
{isLogged && (
<>
<p>
<strong>Description:</strong>
{fen.description}
</p>
<p>
<strong>Correct move:</strong>
{fen.san}
</p>
<Button
onClick={() => {
setIndex(index);
//setFen(fen.fen);
//setSan(fen.san);
setIsEditPositionModalVisible(true);
}}
>
<strong>Edit Position</strong> <EditOutlined />
</Button>
<Modal
title="Edit Position"
visible={isEditPositionModalVisible}
onOk={() => setIsEditPositionModalVisible(false)}
onCancel={() => setIsEditPositionModalVisible(false)}
>
{/* formcomponent */}
<FormComponent
description={fen.description}
index={_index}
fen={fen.fen}
san={fen.san}
setFens={setFens}
password={pass}
id={fenId as string}
type={"edit"}
setIsModalVisible={setIsEditPositionModalVisible}
/>
</Modal>
</>
)}
</p>
</Card>
</Col>
)
)}
</Row>
FormComponent 中的代码:
return (
[...]
<Form.Item
name="fen"
label="Fen"
tooltip="add a valid position in Forsyth-Edwards Notation"
initialValue={props.fen}
</Form.Item>
[...]
);
代码的亮点是我在 FormComponent 内部传递数据,并使用它来设置 initialValue。 Form 组件内的所有字段都被初始化为数组的最后一个元素。我尝试根据索引在 onClick 上设置字段,起初它们被正确初始化,但是当我尝试关闭模式并打开另一个模式时,值保持不变..
我正在使用 antd 进行样式设置,但我认为这不相关。
编辑:我刚刚注意到一个奇怪的行为,这有点道理:通过仅使用一个状态变量(即 isEditPositionModalVisible
),我可能会打开所有一次模态和最后呈现的模态在逻辑上是数组中的最后一个。也许这是正确的轨道,但我想不出一种方法来诚实地管理动态呈现的模态。
Edit2:我想我找到了问题,但没有找到解决方案。我将初始值传递给 as 道具,因为我只使用模态的单个实例,所以呈现的值不会改变。我不知道这是否是一个 antd 问题,但显然
Edit3:好的,也许我找到了解决方案,但通过谷歌搜索我找不到任何有用的东西:有没有办法人为地卸载功能组件?这个想法基本上是在模态不显示时销毁组件,并在显示时安装它。它可能会解决所有问题。
Edit4 根据此处的要求,我的代码有一个沙箱:
https://codesandbox.io/embed/react-typescript-forked-j9p17h?fontsize=14&hidenavigation=1&theme=dark
重要的部分在最后,当我穿过沼泽地时。您可以立即注意到,当第二次使用“编辑位置”按钮打开模态时,该特定模态内的表单的 InitialValues 不会改变。
您已经在使用 Antd 表单。您可以使用 antd 表单挂钩来设置、重置和获取值。您不需要将每个 属性 传递给 FormComponent
.
- 首先像这样创建一个 antd 钩子:
const [form] = Form.useForm();
- 当您点击“编辑位置”按钮时,您已经有该特定卡片的
fen
记录,只需使用form.setFieldsValues({...})
设置表单值,如下所示:
<Button
onClick={() => {
form.setFieldsValue(fen);
setIndex(index);
setIsEditPositionModalVisible(true);
}}
>
<strong>Edit Position</strong> <EditOutlined />
</Button>
- 将
form
属性传递给 FormComponent。 - 在您的
PropsInterface
中添加 - 将表单 Prop 传递给 antd 表单
form: FormInstance;
<Form form={form}> </Form>
您不需要在
设置了值Form.Item
中使用 initialValue。由于您已经使用 form.setFieldsValue().当您点击
Add Position
时,只需使用form.resetFields()
重置表格即可。
希望这能解决您的问题。
请关注antd Form API.