如何使这个反应组件可重用并传递动态初始状态?
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 道具会很棒。
要使字段动态化并使组件整体更通用:
- 传递定义单行字段的
fields
属性对象。
- 创建一个实用程序,用
id
包装字段对象以便于识别(这在改变数组行时派上用场,因为使用数组索引将不起作用).
- 调整处理程序以通过
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: "" }} />
我已经创建了这个动态输入 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 道具会很棒。
要使字段动态化并使组件整体更通用:
- 传递定义单行字段的
fields
属性对象。 - 创建一个实用程序,用
id
包装字段对象以便于识别(这在改变数组行时派上用场,因为使用数组索引将不起作用). - 调整处理程序以通过
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: "" }} />