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

ReactJS表单提交后无法更新名人信息:id.findIndex报错排查

问题描述

我有一个存储名人信息的数据库,不同名人的信息展示在不同的折叠面板(Accordion)中,每个折叠面板都配有编辑按钮,点击按钮会打开表单编辑面板内的各类信息字段。

现在无法保存并同步表单输入的内容,尝试保存详情时,在AccordionForm.jsx中遇到以下错误:

id.findIndex is not a function

我怀疑是无法从数据库中获取id导致的。

相关代码

Home.jsx

return (
  <div>
    <div className="app_header">
      <p>Celebrities Wiki List</p>
    </div>

    {data.map(
      ({ id, first, last, dob, gender, picture, country, description }) => (
        <Accordion
          key={id}
          id={id}
          first={first}
          last={last}
          dob={dob}
          gender={gender}
          picture={picture}
          country={country}
          description={description}
        />
      ),
    )}
  </div>
);

Accordion.jsx

const Accordion = (props) => {
  const [isActive, setIsActive] = React.useState(false);

  const [showModal, setShowModal] = React.useState(false);

  return (
    <div className="accordion-container">
      <div className="accordion-item">
        <div className="accordion-title" onClick={() => setIsActive(!isActive)}>
          <div className="accordion-head">
            <img src={props.picture} alt="celebrity-img" />
            <div className="name">
              {props.first} {props.last}
            </div>
          </div>

          <div>
            {isActive ? (
              <SlArrowUp fontSize={20} color="#a4a597" cursor="pointer" />
            ) : (
              <SlArrowDown fontSize={20} color="#a4a597" cursor="pointer" />
            )}
          </div>
        </div>

        {showModal ? (
          <AccordionForm
            id={props.id}
            age={props.age}
            gender={props.gender}
            country={props.country}
            description={props.description}
            updateAccordion={props.updateAccordion}
            onClose={() => setShowModal(false)}
          />
        ) : (
          <>
            {isActive && (
              <div className="accordion-body">
                <div className="accordion-info">
                  <div className="age">
                    <p className="info-tag">Age</p>
                    <p className="content-text">{props.dob} Years</p>
                  </div>

                  <div className="gender">
                    <p className="info-tag">Gender</p>
                    <p className="content-text">{props.gender}</p>
                  </div>

                  <div className="country">
                    <p className="info-tag">Country</p>
                    <p className="content-text">{props.country}</p>
                  </div>
                </div>

                <div className="accordion-content">
                  <p className="info-tag">Description</p>
                  <p className="content-text">{props.description}</p>
                </div>

                <div className="accordion-buttons">
                  <BsTrash3 fontSize={20} color="red" cursor="pointer" />
                  <BsPencil
                    fontSize={20}
                    color="blue"
                    cursor="pointer"
                    onClick={() => setShowModal(true)}
                  />
                </div>
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
};

AccordionForm.jsx

const AccordionForm = (props) => {
  const [values, setValues] = React.useState({ ...props });

  const updateAccordion = (id) => {
    const index = id.findIndex((item) => item.id === id);
    if (index < 0) return;
  };

  React.useEffect(() => {
    if (
      values.id === props.id &&
      values.first === props.first &&
      values.last === props.last &&
      values.description === props.description &&
      values.country === props.country &&
      values.age === props.age &&
      values.gender === props.gender
    )
      return;

    updateAccordion(props.id, values);
  }, [values]);

  return (
    <Modal onClose={() => props.onClose()}>
      <div className="accordion-body">
        <div className="accordion-info">
          <div className="age">
            <p className="info-tag">Age</p>

            <Editable
              text={values.age}
              default={values.age}
              placeholder="Enter Age"
              onSubmit={(value) => setValues({ ...values, age: value })}
            />
          </div>

          <div className="gender">
            <p className="info-tag">Gender</p>

            <Editable
              text={values.gender}
              default={values.gender}
              placeholder="State Your Gender"
              onSubmit={(value) => setValues({ ...values, gender: value })}
            />
          </div>

          <div className="country">
            <p className="info-tag">Country</p>

            <Editable
              text={values.country}
              default={values.country}
              placeholder="Enter Country"
              onSubmit={(value) => setValues({ ...values, country: value })}
            />
          </div>
        </div>

        <div className="accordion-content">
          <p className="info-tag">Description</p>

          <Editable
            name={values.description}
            default={values.description}
            placeholder="Enter Description"
            onSubmit={(value) => setValues({ ...values, description: value })}
          />
        </div>

        <div className="accordion-buttons">
          <button type="submit">
            <img className="form-check" type src={check} alt="save" />
          </button>

          <button>
            <img
              className="form-cross"
              src={cross}
              alt="close"
              onClick={() => props.onClose()}
            />
          </button>
        </div>
      </div>
    </Modal>
  );
};
const Modal = (props) => {
  return (
    <div
      className="modal"
      onClick={() => (props.onClose ? props.onClose() : "")}
    >
      <div
        className="modal_content"
        onClick={(event) => event.stopPropagation()}
      >
        {props.children}
      </div>
    </div>
  );
};
问题原因与修复

核心错误原因

id.findIndex is not a function 错误的直接原因是:在AccordionForm.jsx的updateAccordion函数中,你把单个id值当成了数组来调用findIndex方法。props.id是单个名人的id(字符串或数字类型),而findIndex是数组的专属方法,因此触发报错。

同时还存在几个关联问题:

  1. updateAccordion函数定义只接收id参数,但调用时传了props.id和values两个参数,参数不匹配。
  2. 数据源(data数组)未传递到更新逻辑中,updateAccordion找不到要修改的目标数组。
  3. Home.jsx到Accordion再到AccordionForm的updateAccordion方法传递链断裂,Accordion未接收并传递该方法。
  4. Accordion里用props.dob展示年龄,但传给AccordionForm的是props.age,字段不匹配。

分步修复

1. 修复数据源与更新逻辑(Home.jsx)

将data改为状态变量,定义更新函数并传递给Accordion组件:

const [data, setData] = React.useState(你的初始名人数据);

const updateAccordion = (id, updatedValues) => {
  setData(prevData => {
    return prevData.map(item => {
      if (item.id === id) {
        return { ...item, ...updatedValues };
      }
      return item;
    });
  });
};

// 渲染时传递updateAccordion给Accordion
{data.map(
  ({ id, first, last, dob, gender, picture, country, description }) => (
    <Accordion
      key={id}
      id={id}
      first={first}
      last={last}
      dob={dob}
      gender={gender}
      picture={picture}
      country={country}
      description={description}
      updateAccordion={updateAccordion}
    />
  ),
)}

2. 修复Accordion组件的字段传递(Accordion.jsx)

将展示的dob作为age传给AccordionForm,保持字段一致:

<AccordionForm
  id={props.id}
  age={props.dob} // 替换props.age为props.dob,和面板展示内容匹配
  gender={props.gender}
  country={props.country}
  description={props.description}
  updateAccordion={props.updateAccordion}
  onClose={() => setShowModal(false)}
/>

3. 重构AccordionForm.jsx的更新逻辑

删除组件内部无效的updateAccordion函数,直接使用props传递的更新方法,改用按钮点击触发保存:

const AccordionForm = (props) => {
  const [values, setValues] = React.useState({
    id: props.id,
    age: props.age,
    gender: props.gender,
    country: props.country,
    description: props.description
  });

  const handleSave = () => {
    props.updateAccordion(props.id, values);
    props.onClose();
  };

  return (
    <Modal onClose={() => props.onClose()}>
      <div className="accordion-body">
        <div className="accordion-info">
          <div className="age">
            <p className="info-tag">Age</p>
            <Editable
              text={values.age}
              default={values.age}
              placeholder="Enter Age"
              onSubmit={(value) => setValues({ ...values, age: value })}
            />
          </div>
          <div className="gender">
            <p className="info-tag">Gender</p>
            <Editable
              text={values.gender}
              default={values.gender}
              placeholder="State Your Gender"
              onSubmit={(value) => setValues({ ...values, gender: value })}
            />
          </div>
          <div className="country">
            <p className="info-tag">Country</p>
            <Editable
              text={values.country}
              default={values.country}
              placeholder="Enter Country"
              onSubmit={(value) => setValues({ ...values, country: value })}
            />
          </div>
        </div>
        <div className="accordion-content">
          <p className="info-tag">Description</p>
          <Editable
            text={values.description} // 替换name为text,和其他字段属性一致
            default={values.description}
            placeholder="Enter Description"
            onSubmit={(value) => setValues({ ...values, description: value })}
          />
        </div>
        <div className="accordion-buttons">
          <button type="button" onClick={handleSave}>
            <img className="form-check" src={check} alt="save" />
          </button>
          <button>
            <img
              className="form-cross"
              src={cross}
              alt="close"
              onClick={() => props.onClose()}
            />
          </button>
        </div>
      </div>
    </Modal>
  );
};

4. 额外优化点

  • 移除原表单按钮的type="submit"(无<form>标签时无效),改为type="button"并绑定handleSave事件。
  • 统一Editable组件的属性名,将描述字段的name改为text,保持一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 11:14:51