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

如何将React-mentions组件与Material-UI(MUI) TextField结合使用?

问题描述

我正在开发应用的评论区,已经基于Material-UI(MUI)的TextField完成了样式和功能开发,效果符合预期。现在想集成react-mentions组件,希望找到不用替换现有TextField的可行方案。

我尝试过两种方式:

  1. 自定义组件方案:写了一个结合两者的组件,但TypeScript下遇到类型/接口错误,代码示例如下:
import React from 'react';
import { MentionsInput, Mention } from 'react-mentions';
import TextField, { TextFieldProps } from '@material-ui/core/TextField';

interface MentionTextFieldProps extends TextFieldProps {
  mentionsProps: {
    value: string;
    onChange: (value: string) => void;
  };
}

const MentionTextField: React.FC<MentionTextFieldProps> = ({
  mentionsProps,
  ...textFieldProps
}) => {
  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    const { value } = event.target;
    mentionsProps.onChange(value);
  };

  return (
    <TextField
      {...textFieldProps}
      onChange={handleChange}
      multiline
      inputProps={{
        style: { lineHeight: '1.5', whiteSpace: 'pre-wrap' },
      }}
    >
      <MentionsInput value={mentionsProps.value} onChange={mentionsProps.onChange}>
        <Mention
          trigger="@"
          data={[]}
        />
      </MentionsInput>
    </TextField>
  );
};

export default MentionTextField;
  1. 直接嵌套方案:把MentionsInput放在TextField的子元素里,代码不报错但react-mentions完全不生效,示例如下:
<TextField
  id="comment-field"
  onChange={handleChange}
  onKeyUp={handleKeyUp}
  name="comment"
  label="Leave a comment"
  multiline
  fullWidth
  minRows={2}
  placeholder="..."
  helperText={validationError ? errors[validationError] : ""}
  error={!!validationError}
  disabled={conditionsThatMakeTheTextFieldDisabled}
  sx={(theme) => ({
    backgroundColor:
      context === "someSortOfContext"
        ? theme.palette.highlight.main
        : theme.palette.background.paper,
  })}
  color={context === "internal" ? "warning" : "primary"}
>
  <MentionsInput
    value={commentValue}
    singleLine={false}
    onChange={(e) => setCommentValue(e.target.value)}
  >
    <Mention trigger="@" data={realUsers} />
  </MentionsInput>
</TextField>

单独使用react-mentions是正常工作的,但我不想替换现有的TextField组件。


可行的集成方案

核心思路是利用MUI TextField的inputComponent属性,将默认的输入组件替换为MentionsInput,同时保留TextField的所有样式和功能,这是官方支持的合规集成方式,能避免嵌套导致的DOM层级冲突。

1. 类型定义(解决TS类型问题)

先扩展TextField的Props,合并react-mentions所需的配置,确保类型安全:

import React from 'react';
import { MentionsInput, Mention, MentionsInputProps } from 'react-mentions';
import TextField, { TextFieldProps } from '@mui/material/TextField';

// 合并TextField属性与MentionsInput的核心配置
type MuiMentionsTextFieldProps = TextFieldProps & {
  mentions: Array<React.ReactElement<typeof Mention>>;
  mentionsInputProps?: Omit<MentionsInputProps, 'value' | 'onChange' | 'children'>;
};

2. 实现自定义组件

创建组件,通过inputComponent把MentionsInput注入到TextField中,同时适配回调格式以兼容原有逻辑:

const MuiMentionsTextField: React.FC<MuiMentionsTextFieldProps> = ({
  mentions,
  mentionsInputProps,
  value,
  onChange,
  multiline = true,
  ...textFieldProps
}) => {
  // 适配react-mentions的onChange回调,模拟TextField的ChangeEvent结构
  const handleMentionsChange = (newValue: string) => {
    onChange?.({
      target: { value: newValue, name: textFieldProps.name },
    } as React.ChangeEvent<HTMLTextAreaElement>);
  };

  // 封装MentionsInput作为自定义输入组件
  const CustomInput = React.forwardRef<HTMLDivElement, MentionsInputProps>((props, ref) => (
    <MentionsInput
      ref={ref}
      value={value as string}
      onChange={handleMentionsChange}
      singleLine={!multiline}
      {...mentionsInputProps}
    >
      {mentions}
    </MentionsInput>
  ));

  return (
    <TextField
      {...textFieldProps}
      value={value}
      onChange={undefined} // 禁用TextField自身的onChange,改用Mentions的回调
      multiline={multiline}
      inputComponent={CustomInput}
      inputProps={{
        ...textFieldProps.inputProps,
        style: { lineHeight: '1.5', whiteSpace: 'pre-wrap' },
      }}
    />
  );
};

3. 使用方式

直接像普通TextField一样使用,同时传入mentions配置,完全复用原有TextField的所有属性:

<MuiMentionsTextField
  id="comment-field"
  name="comment"
  label="Leave a comment"
  fullWidth
  minRows={2}
  placeholder="..."
  helperText={validationError ? errors[validationError] : ""}
  error={!!validationError}
  disabled={conditionsThatMakeTheTextFieldDisabled}
  sx={(theme) => ({
    backgroundColor:
      context === "someSortOfContext"
        ? theme.palette.highlight.main
        : theme.palette.background.paper,
  })}
  color={context === "internal" ? "warning" : "primary"}
  value={commentValue}
  onChange={(e) => setCommentValue(e.target.value)}
  mentions={[
    <Mention key="user" trigger="@" data={realUsers} />,
    // 可添加更多mention类型,比如#话题
    // <Mention key="topic" trigger="#" data={topics} />
  ]}
  mentionsInputProps={{
    // 可选:配置react-mentions的额外属性,比如弹窗位置
    popupPosition: "bottom",
  }}
/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 04:50:16