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

React中基于react-multi-email实现多邮箱字段的编辑功能

给react-multi-email添加邮箱编辑功能的解决方案

由于react-multi-email本身没有内置编辑功能,我们可以通过自定义getLabel属性结合组件内部状态,实现点击标签修改邮箱的功能,具体实现步骤如下:

1. 扩展组件状态

首先在组件的状态接口和初始state中,添加用于跟踪编辑状态的变量:

interface IState {
  emails: string[];
  editingIndex: number; // 当前正在编辑的邮箱索引,-1表示无编辑状态
  editValue: string; // 编辑时的临时输入值
}

class App extends React.Component<IProps, IState> {
  state = {
    emails: [],
    editingIndex: -1,
    editValue: ""
  };
}

2. 编写编辑相关的处理函数

添加三个核心处理函数,分别负责进入编辑状态、保存编辑结果、取消编辑:

// 进入编辑状态,记录当前索引和原邮箱内容
handleEditStart = (index: number, email: string) => {
  this.setState({
    editingIndex: index,
    editValue: email
  });
};

// 保存编辑后的邮箱,先验证格式再更新列表
handleEditSave = (index: number) => {
  const { emails, editValue } = this.state;
  const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(editValue);
  
  if (isValidEmail) {
    const newEmails = [...emails];
    newEmails[index] = editValue;
    this.setState({
      emails: newEmails,
      editingIndex: -1,
      editValue: ""
    });
  } else {
    alert("请输入有效的邮箱地址");
    this.setState({
      editingIndex: -1,
      editValue: ""
    });
  }
};

// 取消编辑,重置状态
handleEditCancel = () => {
  this.setState({
    editingIndex: -1,
    editValue: ""
  });
};

3. 自定义标签渲染逻辑(修改getLabel)

在getLabel回调中,根据当前编辑状态切换显示普通标签或编辑输入框:

getLabel={(email: string, index: number, removeEmail: (index: number) => void) => {
  const { editingIndex, editValue } = this.state;
  
  // 处于编辑状态时,显示输入框
  if (editingIndex === index) {
    return (
      <div data-tag key={index} style={{ display: "inline-flex", alignItems: "center", gap: "4px", margin: "4px" }}>
        <input
          type="text"
          value={editValue}
          onChange={(e) => this.setState({ editValue: e.target.value })}
          onKeyDown={(e) => {
            e.key === "Enter" && this.handleEditSave(index);
            e.key === "Escape" && this.handleEditCancel();
          }}
          onBlur={() => this.handleEditSave(index)}
          autoFocus
          style={{ padding: "4px 6px", border: "1px solid #ccc", borderRadius: "4px" }}
        />
        <span onClick={() => this.handleEditCancel()} style={{ cursor: "pointer", padding: "0 4px" }}>✕</span>
      </div>
    );
  }

  // 非编辑状态,显示带删除、编辑按钮的普通标签
  return (
    <div data-tag key={index} style={{ display: "inline-flex", alignItems: "center", gap: "4px", margin: "4px" }}>
      {email}
      <span data-tag-handle onClick={() => removeEmail(index)} style={{ cursor: "pointer", padding: "0 4px" }}>×</span>
      <span onClick={() => this.handleEditStart(index, email)} style={{ cursor: "pointer", padding: "0 4px", fontSize: "12px" }}>✏️</span>
    </div>
  );
}}

完整修改后的代码

import * as React from "react";
import { render } from "react-dom";
import { ReactMultiEmail } from "react-multi-email";
import "react-multi-email/style.css";

const styles = {
  fontFamily: "sans-serif",
  width: "500px",
  border: "1px solid #eee",
  background: "#f3f3f3",
  padding: "25px",
  margin: "20px"
};

interface IProps {}
interface IState {
  emails: string[];
  editingIndex: number;
  editValue: string;
}

class App extends React.Component<IProps, IState> {
  state = {
    emails: [],
    editingIndex: -1,
    editValue: ""
  };

  handleEditStart = (index: number, email: string) => {
    this.setState({
      editingIndex: index,
      editValue: email
    });
  };

  handleEditSave = (index: number) => {
    const { emails, editValue } = this.state;
    const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(editValue);
    
    if (isValidEmail) {
      const newEmails = [...emails];
      newEmails[index] = editValue;
      this.setState({
        emails: newEmails,
        editingIndex: -1,
        editValue: ""
      });
    } else {
      alert("请输入有效的邮箱地址");
      this.setState({
        editingIndex: -1,
        editValue: ""
      });
    }
  };

  handleEditCancel = () => {
    this.setState({
      editingIndex: -1,
      editValue: ""
    });
  };

  render() {
    const { emails } = this.state;

    return (
      <div style={styles}>
        <h3>react-multi-email 带编辑功能</h3>
        <ReactMultiEmail
          placeholder="Input your Email Address"
          emails={emails}
          onChange={(_emails: string[]) => {
            this.setState({ emails: _emails });
          }}
          getLabel={(email: string, index: number, removeEmail: (index: number) => void) => {
            const { editingIndex, editValue } = this.state;
            
            if (editingIndex === index) {
              return (
                <div data-tag key={index} style={{ display: "inline-flex", alignItems: "center", gap: "4px", margin: "4px" }}>
                  <input
                    type="text"
                    value={editValue}
                    onChange={(e) => this.setState({ editValue: e.target.value })}
                    onKeyDown={(e) => {
                      e.key === "Enter" && this.handleEditSave(index);
                      e.key === "Escape" && this.handleEditCancel();
                    }}
                    onBlur={() => this.handleEditSave(index)}
                    autoFocus
                    style={{ padding: "4px 6px", border: "1px solid #ccc", borderRadius: "4px" }}
                  />
                  <span onClick={() => this.handleEditCancel()} style={{ cursor: "pointer", padding: "0 4px" }}>✕</span>
                </div>
              );
            }

            return (
              <div data-tag key={index} style={{ display: "inline-flex", alignItems: "center", gap: "4px", margin: "4px" }}>
                {email}
                <span data-tag-handle onClick={() => removeEmail(index)} style={{ cursor: "pointer", padding: "0 4px" }}>×</span>
                <span onClick={() => this.handleEditStart(index, email)} style={{ cursor: "pointer", padding: "0 4px", fontSize: "12px" }}>✏️</span>
              </div>
            );
          }}
        />
        <br />
        <p>当前邮箱列表: {emails.join(", ")}</p>
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

功能说明

  • 点击标签上的✏️图标,进入编辑状态,原邮箱内容转为可编辑输入框
  • 编辑时按Enter键或点击输入框外部,自动验证邮箱格式并保存修改
  • 按Escape键或点击输入框旁的✕,取消编辑并恢复原邮箱内容
  • 原有的删除标签功能保持正常使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:16:11