You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为当前版本Autocomplete封装带状态管理的可复用组件

可复用Autocomplete组件抽离方案

核心思路是把重复的状态定义、值处理逻辑、选项label解析逻辑封装在组件内部,把随业务场景变化的配置(选项数据、标签文本、宽度、默认值、值变更回调等)抽为props,使用时不需要重复编写useState和重复的处理逻辑。

封装后的通用组件代码

import { useState } from 'react';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';

const CommonAutocomplete = ({
  options = [],
  label = '',
  width = 300,
  required = false,
  defaultValue = '',
  optionLabelKey = 'firstName',
  onValueChange = () => {}
}) => {
  // 内部维护选中状态,父组件无需重复定义useState
  const [selectedValue, setSelectedValue] = useState(defaultValue);

  // 统一处理freeSolo模式下的值解析逻辑
  const handleValueChange = (_, newValue) => {
    let finalVal;
    if (typeof newValue === 'string') {
      finalVal = newValue;
    } else if (newValue?.inputValue) {
      finalVal = newValue.inputValue;
    } else {
      finalVal = newValue;
    }
    setSelectedValue(finalVal);
    onValueChange(finalVal);
  };

  // 统一处理选项文本解析
  const resolveOptionLabel = (option) => {
    if (typeof option === 'string') return option;
    if (option.inputValue) return option.inputValue;
    return option[optionLabelKey];
  };

  return (
    <Autocomplete
      required={required}
      value={selectedValue}
      onChange={handleValueChange}
      selectOnFocus
      clearOnBlur
      handleHomeEndKeys
      freeSolo
      options={options}
      getOptionLabel={resolveOptionLabel}
      renderOption={(props, option) => <li {...props}>{option[optionLabelKey]}</li>}
      sx={{ width }}
      renderInput={(params) => <TextField {...params} label={label} />}
    />
  );
};

export default CommonAutocomplete;

使用方式

使用时不需要单独编写状态管理和重复的处理逻辑,只需要传入对应场景的配置即可:

import CommonAutocomplete from './CommonAutocomplete';

const FormPage = () => {
  const userOptions = [
    {firstName: '张三'},
    {firstName: '李四'},
    {firstName: '王五'}
  ];

  // 需要获取选中值时,传入回调即可
  const handleNameGet = (val) => {
    console.log('当前选中值:', val);
    // 在这里写后续业务逻辑,比如表单提交、字段联动
  };

  return (
    <div style={{padding: 24}}>
      {/* 第一个实例:名 */}
      <CommonAutocomplete
        required
        options={userOptions}
        label="First Name"
        onValueChange={handleNameGet}
      />

      {/* 第二个实例:联系人,自定义宽度和默认值 */}
      <CommonAutocomplete
        options={userOptions}
        label="紧急联系人"
        width={400}
        defaultValue="张三"
      />
    </div>
  );
};

可选扩展

  • 如果需要支持表单场景下的受控需求(比如外部重置值、批量赋值),可以增加受控逻辑判断:如果父组件传入value和onChange props,就优先使用父组件传入的状态和回调,否则使用组件内部state,同时兼容受控、非受控两种使用模式。
  • 如果不同场景下选项渲染、输入框渲染逻辑差异较大,可以把renderOption、renderInput也作为可选props传入,支持自定义覆盖默认渲染逻辑。
  • 固定的全局配置(比如通用宽度、通用校验规则)可以直接写在封装组件内部,减少使用时的重复传参。

内容的提问来源于stack exchange,提问作者Shoppe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 08:39:29