封装 Antd Input [1]

31 阅读1分钟

封装既可显示文本又可编辑文本的组件

img_v3_02sm_4740abfe-4d4d-4710-904b-586da20456cg.jpg

import { EditOutlined } from '@ant-design/icons';
import { Input, InputProps } from 'antd';
import { ChangeEvent, useState } from 'react';

interface EditTextInputProps extends Omit<InputProps, 'value' | 'onChange' | 'onPressEnter'> {
  value?: string;
  onChange?: (value: string) => void;
  onPressEnter?: () => void;
  defaultValue?: string;
}

const EditTextInput: React.FC<EditTextInputProps> = ({
  value: propsValue,
  onChange: propsOnChange,
  onPressEnter: propsOnPressEnter,
  defaultValue = '',
  ...restProps
}) => {
  const [internalValue, setInternalValue] = useState<string>(
    propsValue !== undefined ? propsValue : defaultValue
  );

  const [showInput, setShowInput] = useState(false);

  const handlePressEnter = async () => {
    if (propsOnPressEnter) {
      await propsOnPressEnter();
    }
    setShowInput(false);
  };

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    const newValue = e.target.value;
    setInternalValue(newValue); // 始终更新内部状态,保证响应迅速
    if (propsOnChange) {
      propsOnChange(newValue); // 将新值传递给外部
    }
  };

  // 决定显示哪个值:如果外部提供了value,使用外部的值(受控模式)
  const displayValue = propsValue !== undefined ? propsValue : internalValue;
  return (
    <>
      {!showInput && (
        <>
          <span title={internalValue}>{internalValue}</span>
          <span onClick={() => setShowInput(true)}>
            <EditOutlined />
          </span>
        </>
      )}
      {showInput && (
        <Input
          value={displayValue}
          onPressEnter={handlePressEnter}
          onChange={handleChange}
          {...restProps}
        />
      )}
    </>
  );
};

export default EditTextInput;