react 动态创建ref

164 阅读1分钟

开始做react了,遇到了第一个稍微复杂的问题。记录一下

背景

有多个模块,是动态新增的,模块内有校验,获取数据,需要通过父组件调用子组件的ref方法进行校验

核心是通过函数实时给ref赋值

return (
    <input ref={(r)=>{
    // 动态赋值
}} />
)

实时查看

codesandbox.io/p/sandbox/m…

代码


import { FC, forwardRef, useImperativeHandle, useState } from 'react';

// react ant design 是通过form自动收集,此处可以不传value和onChange
type InputCustomProps = {
  value?: string;
  onChange?: (x: InputCustomProps['value']) => void;
};
// 自定义输入框组件的ref接口
type InputCustomExposeHandle = {
  validate: () => Promise<boolean>;
};

// 自定义输入框组件
export const InputCustom = forwardRef<InputCustomExposeHandle, InputCustomProps>(
  ({ value, onChange }, ref) => {
    useImperativeHandle(ref, () => ({
      validate: async () => {
        return Math.random() > 0.5 ? true : false;
      },
    }));
    return <input value={value} onChange={e => onChange?.(e.target.value)} />;
  }
);

// 功能配置
const DynamicRefTest: FC = () => {
  const mapRef = new Map<string, InputCustomExposeHandle>();
  const [list, setList] = useState<Array<string>>([]);

  return (
    <div>
      <button
        onClick={() => {
          setList([...list, '']);
        }}>
        新增
      </button>
      <button
        onClick={async () => {
          console.log(mapRef);
          console.log(await mapRef.get('list-0')?.validate());
        }}>
        打印ref
      </button>
      {list.map((item, index) => (
        <div key={index}>
          <InputCustom
            ref={r => {
              return mapRef.set(`list-${index}`, r!);
            }}
            value={item}
            onChange={value => {
              console.log('value :>> ', value);
              if (!value) return;
              const _list = [...list];
              _list[index] = value;
              setList(_list);
            }}
          />
          <button
            onClick={() => {
              setList(list.filter((_, i) => i !== index));
            }}>
            删除
          </button>
        </div>
      ))}
    </div>
  );
};

export default DynamicRefTest;