Ant Design Form.Item 中使用 Select 组件默认值总是显示数字

文章目录

    现象

    在 Antd Pro 中使用了 Antd Form 来编辑报修单的进度状态。

    但是在选中一条记录,在使用 Select 组件进行编辑时,总是显示状态码,而非状态描述。

    看起来是之前遇到过的,select value 的整型与字符串的转换问题。

    Warning: children should be Select.Option or Select.OptGroup instead of Option

    原始代码:

    <Form.Item name="status" label="状态">
      <Select>
    	<Option value="1">待处理</Option>
    	<Option value="2">处理中</Option>
    	<Option value="3">已完成</Option>
      </Select>
    </Form.Item>
    

    Chrome Console 中显示警告信息:

    Warning: children should be Select.Option or Select.OptGroup instead of Option

    vscode 中直接报错:

    JSX element class does not support attributes because it does not have a 'props' property.
    
    'Option' cannot be used as a JSX component.
    Its instance type 'HTMLOptionElement' is not a valid JSX element.
    Type 'HTMLOptionElement' is missing the following properties from type 'ElementClass': render, context, setState, forceUpdate, and 3 more.
    
    

    按照提示,修改为:

    <Form.Item name="status" label="状态">
      <Select>
    	<Select.Option value="1">待处理</Select.Option>
    	<Select.Option value="2">处理中</Select.Option>
    	<Select.Option value="3">已完成</Select.Option>
      </Select>
    </Form.Item>
    

    没有报错了,但是,还是只显示 1, 而非状态描述 “待处理”。

    解决方法一

    在选中要修改的行时,将对应的字段值由整型转换成字符串。

    <a
      key="config"
      onClick={() => {
    	handleFormVisible(true);
    	record.status += ""
    	setCurrentRow(record);
      }}
    >
      编辑
    </a>,
    

    这样 Form 在处理时,初始化值就变成字符串 “1”,于是显示就正常了。

    (最佳) 解决方法二

    参考:

    https://ant.design/components/select-cn/#API

    可以看到 select 组件有个 options 属性:

    options 数据化配置选项内容,相比 jsx 定义会获得更好的渲染性能 { label, value }[]

    何不尝试一下,于是修改了一下:

    const options = [
      {
    	label: "待处理",
    	value: 1,
      },
      {
    	label: "处理中",
    	value: 2,
      },
      {
    	label: "已完成",
    	value: 3,
      },
    ];
    
    ...
    
    <Form.Item name="status" label="状态">
      <Select options={options}>
      </Select>
    </Form.Item>
    

    这样就能保证 value 是整型,跟服务端返回的类型一致。

    测试了一下,果然可以。幸好没有用 ProForm 的方案。

    (无效) 尝试 ProComponents ProFormSelect 组件

    虽然我很厌恶 ProComponents 这种对低质量代码再进行低质量封装的行为,但是没办法只能硬着头皮试试了。

    import { ProFormSelect } from '@ant-design/pro-form';
    
    <ProFormSelect
        name="status"
        label="status"
        valueEnum={{
          1: '未解决',
          3: '已解决',
        }}
        placeholder="Please select a country"
      />
    

    也不行, 还是显示 1。

    (无效) 设置 valuePropName

    参考:

    https://github.com/ant-design/ant-design/issues/5226

    I have found that you have to set valuePropName to “option” in the getFieldDecorator options in order for the placeholder text to show, but I can’t find any documentation on this, so I wanted to share incase other people have run into the same issue.

    {getFieldDecorator('roleList', {
      initialValue: user.roleList || [],
      valuePropName: 'option',
      rules: [
        { required: false, message: 'Assign roles for this user', type: 'array' },
      ],
    })(
      <Select mode="multiple" placeholder="Assign roles for this user">
        <Select.Option value="role_admin">Administrator</Select.Option>
        <Select.Option value="role_seller">Seller</Select.Option>
        <Select.Option value="role_customer">Customer</Select.Option>
      </Select>
    )}
    

    对应的,我在 Select 组件上添加了 valuePropName 属性,值为 option。

    这下可好,啥也不显示了。而且也说不通。

    虽然无效,但是了解了有 valuePropName 这个属性的存在,可以自定义非 value 属性的设置,非常好。

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式