Skip to content

Conversation

@RylanBot
Copy link
Collaborator

@RylanBot RylanBot commented Dec 9, 2025

🤔 这个 PR 的性质是?

  • 日常 bug 修复
  • 新特性提交
  • 文档改进
  • 演示代码改进
  • 组件样式/交互改进
  • CI/CD 改进
  • 重构
  • 代码风格优化
  • 测试用例
  • 分支合并
  • 其他

🔗 相关 Issue

💡 需求背景和解决方案

场景 2 代码存档
import React, { useState } from 'react';
import { Button, Dialog, Form, Input } from 'tdesign-react';

const { FormItem, FormList } = Form;

export default function DynamicFormList() {
  const [mainForm] = Form.useForm();
  const [dialogForm] = Form.useForm();

  const [visible, setVisible] = useState(false);
  const [editingIndex, setEditingIndex] = useState(null);

  const openDialog = (index) => {
    setEditingIndex(index);
    const value = mainForm.getFieldValue(['main', index, 'userAmount']) || '';
    dialogForm.setFieldsValue({ amount: value });
    setVisible(true);
  };

  const handleConfirm = async () => {
    const amount = dialogForm.getFieldValue('amount');
    console.log('Dialog 确认保存,输入金额:', amount);
    mainForm.setFieldsValue({
      main: mainForm
        .getFieldValue('main')
        .map((item, idx) => (idx === editingIndex ? { ...item, userAmount: amount } : item)),
    });

    setVisible(false);
  };

  return (
    <>
      <Form form={mainForm}>
        <FormList name="main">
          {(fields, { add }) => (
            <>
              {fields.map(({ key, name }) => (
                <div key={key} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                  <FormItem name={[name, 'userAmount']} label={`用户金额 ${name + 1}`}>
                    <Input disabled placeholder="点击右侧按钮设置金额" />
                  </FormItem>

                  <Button theme="primary" variant="text" onClick={() => openDialog(name)}>
                    设置金额
                  </Button>
                </div>
              ))}

              <Button block variant="dashed" onClick={() => add({ userAmount: '' })}>
                新增一项
              </Button>

              <Dialog
                visible={visible}
                confirmBtn="确认保存"
                cancelBtn="取消"
                onConfirm={handleConfirm}
                onCancel={() => setVisible(false)}
                header="输入金额"
              >
                <Form
                  form={dialogForm}
                  onValuesChange={(c, all) => {
                    const amount = dialogForm.getFieldValue('amount');
                    console.log(c, all, amount);
                  }}
                >
                  <FormItem name="amount" label="金额" rules={[{ required: true, message: '金额不能为空' }]}>
                    <Input placeholder="请输入金额,例如 100" />
                  </FormItem>
                </Form>
              </Dialog>
            </>
          )}
        </FormList>
      </Form>
    </>
  );
}

日志 3➕4 的复现:手动把「请求限流」的 Radio 切换到 「QPS」后再 add,新项的 shouldUpdate 里面渲染了「QPS」,而非 defaultInstance.serviceLimitnone(不限流)

场景 3 ➕ 4 代码存档
import React from 'react';
import { Button, Divider, Form, Input, Radio, Space } from 'tdesign-react';

const { FormItem, FormList } = Form;

const TestView = () => {
  const [form] = Form.useForm();

  const INIT_DATA = {
    services: [
      {
        modelName: 'modelA',
        routes: [
          { type: 'weight', weight: 50, abtest: 'cid' },
          { type: 'abtest', weight: 30, abtest: 'uid' },
        ],
      },
    ],
  };

  return (
    <Form form={form} initialData={INIT_DATA}>
      <FormList name="services">
        {(fields) => (
          <>
            {fields.map(({ key, name: serviceName }) => (
              <div key={key}>
                <FormList name={[serviceName, 'routes']}>
                  {(routeFields, { add: addRoute }) => (
                    <div>
                      {routeFields.map((f) => (
                        <div key={f.key} data-route-index={f.name}>
                          <FormItem name={[f.name, 'type']} label="类型">
                            <Radio.Group
                              options={[
                                { label: '权重', value: 'weight' },
                                { label: 'ABTest', value: 'abtest' },
                              ]}
                            />
                          </FormItem>

                          <FormItem
                            shouldUpdate={(p, n) =>
                              p.services?.[serviceName]?.routes?.[f.name]?.type !==
                              n.services?.[serviceName]?.routes?.[f.name]?.type
                            }
                          >
                            {({ getFieldValue }) => {
                              const type = getFieldValue(['services', serviceName, 'routes', f.name, 'type']);
                              if (type === 'weight') {
                                return (
                                  <FormItem
                                    name={[f.name, 'weight']}
                                    label="权重"
                                  >
                                    <Input placeholder={`route-weight-${serviceName}-${f.name}`} />
                                  </FormItem>
                                );
                              }
                              if (type === 'abtest') {
                                return (
                                  <FormItem
                                    name={[f.name, 'abtest']}
                                    label="分流Key"
                                  >
                                    <Input placeholder={`route-abtest-${serviceName}-${f.name}`} />
                                  </FormItem>
                                );
                              }
                              return null;
                            }}
                          </FormItem>

                          <Divider />
                        </div>
                      ))}
                      <Space>
                        <Button id={`test-add-route-${serviceName}-default`} onClick={() => addRoute()}>
                          新增默认路由
                        </Button>
                        <Button
                          id={`test-add-route-${serviceName}-specified`}
                          onClick={() => addRoute(INIT_DATA.services[0].routes[0])}
                        >
                          新增指定路由
                        </Button>
                      </Space>
                    </div>
                  )}
                </FormList>
              </div>
            ))}
          </>
        )}
      </FormList>
    </Form>
  );
};

export default function Test() {
  return <TestView />;
}

📝 更新日志

  • fix(Form): 修复使用 shouldUpdate 时,必须给 FormItemkey 才能生效的问题

  • fix(FormList): 修复子节点存在另一个 Form 时,部分 API 异常的问题

  • fix(FormList): 修复结合 shouldUpdate 使用时,initialData 不生效的问题

  • fix(FormList): 修复 add 过程中缺乏拷贝从而污染用户原始数据的问题

  • 本条 PR 不需要纳入 Changelog

☑️ 请求合并前的自查清单

⚠️ 请自检并全部勾选全部选项⚠️

  • 文档已补充或无须补充
  • 代码演示已提供或无须提供
  • TypeScript 定义已补充或无须补充
  • Changelog 已提供或无须提供

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 9, 2025

  • tdesign-react-demo

    npm i https://pkg.pr.new/Tencent/tdesign-react@4005
    
    npm i https://pkg.pr.new/Tencent/tdesign-react/@tdesign-react/chat@4005
    

commit: 63a0f1e

@github-actions
Copy link
Contributor

github-actions bot commented Dec 9, 2025

完成

@RylanBot RylanBot added the WIP work in porgess label Dec 9, 2025
@RylanBot RylanBot force-pushed the rylan/fix/form/clone branch from 4de66a7 to b415ab7 Compare December 9, 2025 11:32
@RylanBot RylanBot removed the WIP work in porgess label Dec 9, 2025
@RylanBot RylanBot force-pushed the rylan/fix/form/clone branch from b415ab7 to f090f10 Compare December 9, 2025 12:39
@RylanBot RylanBot force-pushed the rylan/fix/form/clone branch from f090f10 to e75b56c Compare December 9, 2025 12:44
@RylanBot RylanBot added WIP work in porgess and removed WIP work in porgess labels Dec 10, 2025
@RylanBot RylanBot force-pushed the rylan/fix/form/clone branch 3 times, most recently from e04d3f0 to 41e3485 Compare December 10, 2025 15:24
@RylanBot RylanBot added the WIP work in porgess label Dec 11, 2025
@RylanBot RylanBot force-pushed the rylan/fix/form/clone branch 2 times, most recently from da55f8c to 95bc7e3 Compare December 12, 2025 10:33
@RylanBot RylanBot force-pushed the rylan/fix/form/clone branch from 95bc7e3 to 6925571 Compare December 12, 2025 16:06
@RylanBot RylanBot removed the WIP work in porgess label Dec 12, 2025
@RylanBot RylanBot force-pushed the rylan/fix/form/clone branch 2 times, most recently from f5f327e to d03f168 Compare December 15, 2025 07:51
@RylanBot RylanBot force-pushed the rylan/fix/form/clone branch from d03f168 to 25201a9 Compare December 15, 2025 08:07
@RylanBot RylanBot force-pushed the rylan/fix/form/clone branch from 330264e to c7a51b9 Compare December 15, 2025 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants