提问者:小点点

将表单提交映射到数组


我正在创建一个用于创建网站主干的表单。因此,您需要能够创建元素,然后将这些元素的值发送到服务器。

我的想法是创建两个useState数组,每个数组都具有相同的对象键,其中一个数组是表单字段,另一个是发送到服务器的对象数据。

页面加载来自服务器的当前评论列表或一个空白评论,理论上这将填充第一个插入的评论。

我想要的是这些文本输入中的onChange方法,它在文本输入数组中查找自身的索引,然后使用该索引在字段响应数组中查找特定对象。

因此,基本上,如果您有30组输入字段,并更新编号29,它将使用目标值更新相应数组中的编号29。下面的on change方法适用于第一个输入,但一旦启动addReview(),存储在第二个数组中的值就会消失,并且只有rev数组中的第一个对象保留数据。

 const [revArr, setRevArr] = useState([
    {
      reviewer: (
        <input
          type='text'
          name='reviewer'
          onChange={(e) => {
            rev.map(() => {
              const i = revArr.map((rev, i) => i);
              let obj = {
                reviewer: e.target.value,
                review: rev[i].review,
                date: rev[i].date,
                pic: rev[i].pic,
              };

              rev[i] = obj;
              console.log(firmObj);
            });
          }}
        />
      ),
      date: (
        <input
          type='text'
          name='date'
          onChange={(e) => {
            rev.map(() => {
              const i = revArr.map((rev, i) => i);
              let obj = {
                reviewer: rev[i].reviewer,
                review: rev[i].review,
                date: e.target.value,
                pic: rev[i].pic,
              };

              rev[i] = obj;
            });
          }}
        />
      ),
      review: (
        <input
          type='text'
          name='review'
          onChange={(e) => {
            rev.map(() => {
              const i = revArr.map((rev, i) => i);
              let obj = {
                reviewer: rev[i].reviewer,
                review: e.target.value,
                date: rev[i].date,
                pic: rev[i].pic,
              };

              rev[i] = obj;
            });
          }}
        />
      ),
      pic: (
        <input
          type='text'
          name='pic1'
          onChange={(e) => {
            rev.map(() => {
              const i = revArr.map((rev, i) => i);
              let obj = {
                reviewer: rev[i].reviewer,
                review: rev[i].review,
                date: rev[i].date,
                pic: e.target.value,
              };

              rev[i] = obj;
            });
          }}
        />
      ),
    },
  ]);

  const addReviewObj = () => {
    setReviews([
      ...rev,
      {
        reviewer: "",
        date: "",
        review: "",
        pic: "",
      },
    ]);
    setRevArr([
      ...revArr,
      {
        reviewer: (
          <input
            type='text'
            name='reviewer'
            onChange={(e) => {
              rev.map(() => {
                const i = revArr.map((rev, i) => i);
                let obj = {
                  reviewer: e.target.value,
                  review: rev[i] ? rev[i].review : "",
                  date: rev[i] ? rev[i].date : "",
                  pic: rev[i] ? rev[i].pic : "",
                };

                rev[i] = obj;
              });
            }}
          />
        ),
        date: (
          <input
            type='text'
            name='date'
            onChange={(e) => {
              rev.map(() => {
                const i = revArr.map((rev, i) => i);
                let obj = {
                  reviewer: rev[i] ? rev[i].reviewer : "",
                  review: rev[i] ? rev[i].review : "",
                  date: e.target.value,
                  pic: rev[i] ? rev[i].pic : "",
                };

                rev[i] = obj;
              });
            }}
          />
        ),
        review: (
          <input
            type='text'
            name='review'
            onChange={(e) => {
              rev.map(() => {
                const i = revArr.map((rev, i) => i);
                let obj = {
                  reviewer: rev[i] ? rev[i].reviewer : "",
                  review: e.target.value,
                  date: rev[i] ? rev[i].date : "",
                  pic: rev[i] ? rev[i].pic : "",
                };

                rev[i] = obj;
              });
            }}
          />
        ),
        pic: (
          <input
            type='text'
            name='pic1'
            onChange={(e) => {
              rev.map(() => {
                const i = revArr.map((rev, i) => i);
                let obj = {
                  reviewer: rev[i] ? rev[i].reviewer : "",
                  review: rev[i] ? rev[i].review : "",
                  date: rev[i] ? rev[i].date : "",
                  pic: e.target.value,
                };

                rev[i] = obj;
              });
            }}
          />
        ),
      },
    ]);
  };





共1个答案

匿名用户

您的问题有点让人困惑,但听起来您想要一个具有动态行数的表单。每行具有固定数量的输入。

您可以将状态保持在单个对象数组中,映射到数组上以呈现每行输入。

输入onChange处理程序将把数组索引和事件传递给函数。

您可以从事件中获取值和输入名称,这些(以及数组索引)是设置新状态的足够信息。

import { useState } from "react";

export default function App() {

  const emptyReview = {
    reviewer: "",
    review: ""
  };

  const [results, setResults] = useState([{ ... emptyReview }]);

  const onChange = (i, e) => {
    const { value, name } = e.currentTarget;
    const newResults = [...results];
    newResults[i] = {
      ...newResults[i],
      [name]: value
    };
    setResults(newResults);
  };

  const addReview = () => {
    const newResults = [...results, { ... emptyReview }];
    setResults(newResults);
  };

  return (
    <div className="App">
      {results.map((result, i) => (
        <div key={i}>
          <div>
            <label>
              reviewer:
              <input
                value={result.reviewer}
                name="reviewer"
                onChange={(e) => onChange(i, e)}
              />
            </label>
          </div>
          <div>
            <label>
              review:
              <input
                value={result.review}
                name="review"
                onChange={(e) => onChange(i, e)}
              />
            </label>
          </div>
          <hr />
        </div>
      ))}
      <button onClick={addReview}>new review</button>
      <pre>{JSON.stringify(results)}</pre>
    </div>
  );
}

奖金如果输入只是相同的文本输入,并且标签重复,则您甚至可以从外部映射中映射对象的键。这样,如果您需要添加额外的字段,您只需在一个位置执行此操作,emptyReview对象。

    {results.map((row, i) => (
      <div key={i} className="row">
        {Object.keys(row).map((key) => (
          <label key={key}>
            {key}
            <input
              value={row[key]}
              name={key}
              onChange={(e) => onChange(i, e)}
            />
          </label>
        ))}
      </div>
    ))}