如何使这个反应组件可重用并传递动态初始状态?

How can I make this react component reusable and pass a dynamic initial state?

我已经创建了这个动态输入 table,但我想让它可重用并且更动态。在这里,姓名和年龄是静态的。如果我想将姓名、年龄、国家、地区等作为道具发送,此代码将不起作用。我怎样才能做到这一点? 这是我的代码:

import React, { useState } from 'react';

const DynamicTable = () => {
  const [fields, setFields] = useState([{ name: '', age: 0 }]);

  const onChangeHandler = (e, index) => {
    let name = '';
    let age = 0;
    if (e.target.name === 'name') {
      name = e.target.value;
      console.log(name, age);
    } else {
      age = e.target.value;
      console.log(name, age);
    }
    // Set Field Value
    const newFields = fields.map((item, i) => {
      if (index === i) {
        if (e.target.name === 'name') {
          return { ...item, name };
        } else {
          return { ...item, age };
        }
      } else {
        return item;
      }
    });
    setFields(newFields);
    console.log(newFields);
  };

  // For delete button
  const deleteHandler = (index) => {
    const newField = fields.filter((item, i) => i !== index);
    setFields(newField);
  };
  return (
    <div>
      <div>
        <button onClick={() => setFields([...fields, { name: '', age: 0 }])}>
          Add
        </button>
      </div>
      <table>
        <tbody>
          {fields.map((item, index) => (
            <tr key={index}>
              <td>
                Name:
                <input
                  type='text'
                  name='name'
                  onChange={(e) => onChangeHandler(e, index)}
                />
              </td>
              <td>
                Age:
                <input
                  type='text'
                  name='age'
                  onChange={(e) => onChangeHandler(e, index)}
                />
              </td>
              <td>
                <button onClick={() => deleteHandler(index)}>Delete</button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
      <div>
        <button onClick={() => console.log(fields)}>Submit</button>
      </div>
      {/* Test input value working correctly */}
      <div>
        {fields.map((item) => (
          <p>
            {item.name} - {item.age}
          </p>
        ))}
      </div>
      {/* ---- */}
    </div>
  );
};

export default DynamicTable;

注意:如果我们可以根据复选框删除和添加行,那就太好了。此外,为按钮或其他元素应用 CSS throw 道具会很棒。

要使字段动态化并使组件整体更通用:

  1. 传递定义单行字段的 fields 属性对象。
  2. 创建一个实用程序,用 id 包装字段对象以便于识别(这在改变数组行时派上用场,因为使用数组索引将不起作用).
  3. 调整处理程序以通过 id 和新状态形状管理行。

代码:

import React, { useState } from "react";
import { v4 as uuidV4 } from "uuid";
import "./styles.css";

const createFieldsObject = (fields) => ({
  id: uuidV4(), // <-- generate unique Id, can use anything really
  fields
});

const DynamicTable = ({ fields }) => {
  const [fieldRows, setFieldRows] = useState([createFieldsObject(fields)]);

  const onChangeHandler = (id) => (e) => {
    const { name, value } = e.target;

    setFieldRows((rows) =>
      rows.map((row) =>
        row.id === id
          ? {
              ...row,
              fields: {
                ...row.fields,
                [name]: value
              }
            }
          : row
      )
    );
  };

  const addHandler = () =>
    setFieldRows((rows) => [...rows, createFieldsObject(fields)]);

  const deleteHandler = (id) => () =>
    setFieldRows((rows) => rows.filter((row) => row.id !== id));

  const getFieldRows = () => fieldRows.map(({ fields }) => fields);

  const submitHandler = e => {
    e.preventDefault();
    console.log(getFieldRows());
  }

  return (
    <form onSubmit={submitHandler}>
      <div>
        <button onClick={addHandler}>Add</button>
      </div>
      <table>
        <tbody>
          {fieldRows.map(({ id, fields }, index) => (
            <tr key={id}>
              {Object.entries(fields).map(([key, value]) => (
                <td key={key}>
                  {key}:
                  <input
                    type="text"
                    name={key}
                    onChange={onChangeHandler(id)}
                    value={value}
                  />
                </td>
              ))}
              <td>
                <button onClick={deleteHandler(id)}>Delete</button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
      <div>
        <button type="submit">Submit</button>
      </div>
      {/* Test input value working correctly */}
      <div>
        {fieldRows.map(({ id, fields }) => (
          <p key={id}>{Object.values(fields).join(" - ")}</p>
        ))}
      </div>
      {/* ---- */}
    </form>
  );
};

用法示例:

<DynamicTable fields={{ Name: "", Age: 0 }} />
<DynamicTable fields={{ Name: "", Age: 0, Location: "" }} />