动态渲染表单元素并将它们保存在 ReactJS 中的数组中
Dynamically rendering form elements and saving them in an array in ReactJS
我有 3 个 materialUI TextFields,我想渲染 n 次(n 将是用户在呈现表单字段之前输入的整数,这里我将其存储在名为 groupMembersCount) 的变量中。
我在 ReactJS 中使用功能组件定义一个 array with useState hooks as:
const [groupDetails, setGroupDetails] = React.useState([
{ fullName: "", phoneNo: "", gender: "" },
]);
这将是我的主数组,用于在各自的索引处保存所有 3 个值(用户输入)。
我尝试通过这种方法动态返回那些 3 materialUI TextField:
{Array.apply(null, { length: groupMembersCount }).map(
(e, i) => (
<div key={i}>
<strong>Member #{i + 1}</strong>
<div className="getIndex" name={i + 1}>
<TextField
id={Math.random()}
name="Name"
variant="outlined"
margin="none"
label="Name"
onChange={handleGroupName}
/>
<TextField
id={Math.random()}
name="phoneNo"
variant="outlined"
margin="none"
label="Mobile Number"
onChange={handleGroupPhoneNo}
/>
<TextField
id={Math.random()}
name="gender"
variant="outlined"
margin="none"
label="Gender"
onChange={handleGroupGender}
select
>
<option value="MALE">Male</option>
<option value="FEMALE">Female</option>
<option value="OTHER">Other</option>
</TextField>
</div>
</div>
)
)}
现在在名称处理程序中 handleGroupName 我这样做是为了获取 div(从存储索引的名称属性中获取索引以推送此值在主数组 groupDetails):
const handleGroupName = (event) => {
let elem = document.getElementsByClassName("getIndex"); // get div
for (var i = 0; i < groupMembersCount; i++) {
console.log("index is: ", elem[i].getAttribute('name')); // get the index number
}
};
完成所有这些后,我遇到了一些问题:
1. name 属性中带有性别的表单字段 (TextField) 之一,我无法使用 select 创建下拉列表(写入此处显示的内容会导致空白屏幕)所以我把它注释掉了。
2. 在 for 循环内的 handleGroupName 处理程序中,它显示错误为:UserDetails.jsx:434 Uncaught TypeError: Cannot read 属性 'getAttribute' of undefined。
3. 我是 React 功能组件的新手,没有太多经验,谁能建议一些更好的方法来从每个渲染的表单字段中获取值,并将它们作为对象合并并存储在主数组中的不同索引处,主数组的结构 groupDetails 定义了它最后的样子。
请试试这个例子,我输入了在组中定义 number of member
的输入。然后显示 number of input groups
(姓名,phone 和性别)。填写信息后,如果您单击 Show
按钮,您将看到结果。
import TextField from "@material-ui/core/TextField";
import React, {useState} from "react";
import Select from "@material-ui/core/Select";
import Button from "@material-ui/core/Button";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Typography from "@material-ui/core/Typography";
export default function DynamicGroupMember() {
const [groupMembersCount, setGroupMembersCount] = useState(0);
const [show, setShow] = useState(false);
const [groupDetails, setGroupDetails] = useState([
{fullName: "", phoneNo: "", gender: ""},
]);
function handleChange(event, index) {
console.log(event.target.value, index);
let newArr = [...groupDetails]; // copying the old datas array
let item = newArr[index];
item = {...item, [event.target.name]: event.target.value};
newArr[index] = item;
setGroupDetails(newArr);
}
return (
<div>
Number of Group: <TextField name="groupMembersCount" onChange={(event) => {
setGroupMembersCount(event.target.value)
}}/>
{Array.apply(null, {length: groupMembersCount}).map(
(e, i) => (
<div key={i}>
<strong>Member #{i + 1}</strong>
<div className="getIndex" name={i + 1}>
<TextField
id={`name${i + 1}`}
name="fullName"
variant="outlined"
margin="none"
label="Name"
onChange={(event) => {
handleChange(event, i)
}}
/>
<TextField
id={`phoneNo${i + 1}`}
name="phoneNo"
variant="outlined"
margin="none"
label="Mobile Number"
onChange={(event) => {
handleChange(event, i)
}}
/>
<Select
id={`gender${i + 1}`}
name="gender"
variant="outlined"
margin="none"
label="Gender"
onChange={(event) => {
handleChange(event, i)
}}
>
<option value="MALE">Male</option>
<option value="FEMALE">Female</option>
<option value="OTHER">Other</option>
</Select>
</div>
</div>
)
)}
<Button onClick={() => {
setShow(true)
}}>Show</Button>
{
show ?
groupDetails.map(member =>
<Card>
<CardContent>
<Typography color="textSecondary" gutterBottom>
{member.fullName}
</Typography>
<Typography variant="h5" component="h2">
{member.phoneNo}
</Typography>
<Typography color="textSecondary">
{member.gender}
</Typography>
</CardContent>
</Card>) : null
}
</div>
);
}
我有 3 个 materialUI TextFields,我想渲染 n 次(n 将是用户在呈现表单字段之前输入的整数,这里我将其存储在名为 groupMembersCount) 的变量中。 我在 ReactJS 中使用功能组件定义一个 array with useState hooks as:
const [groupDetails, setGroupDetails] = React.useState([
{ fullName: "", phoneNo: "", gender: "" },
]);
这将是我的主数组,用于在各自的索引处保存所有 3 个值(用户输入)。 我尝试通过这种方法动态返回那些 3 materialUI TextField:
{Array.apply(null, { length: groupMembersCount }).map(
(e, i) => (
<div key={i}>
<strong>Member #{i + 1}</strong>
<div className="getIndex" name={i + 1}>
<TextField
id={Math.random()}
name="Name"
variant="outlined"
margin="none"
label="Name"
onChange={handleGroupName}
/>
<TextField
id={Math.random()}
name="phoneNo"
variant="outlined"
margin="none"
label="Mobile Number"
onChange={handleGroupPhoneNo}
/>
<TextField
id={Math.random()}
name="gender"
variant="outlined"
margin="none"
label="Gender"
onChange={handleGroupGender}
select
>
<option value="MALE">Male</option>
<option value="FEMALE">Female</option>
<option value="OTHER">Other</option>
</TextField>
</div>
</div>
)
)}
现在在名称处理程序中 handleGroupName 我这样做是为了获取 div(从存储索引的名称属性中获取索引以推送此值在主数组 groupDetails):
const handleGroupName = (event) => {
let elem = document.getElementsByClassName("getIndex"); // get div
for (var i = 0; i < groupMembersCount; i++) {
console.log("index is: ", elem[i].getAttribute('name')); // get the index number
}
};
完成所有这些后,我遇到了一些问题: 1. name 属性中带有性别的表单字段 (TextField) 之一,我无法使用 select 创建下拉列表(写入此处显示的内容会导致空白屏幕)所以我把它注释掉了。 2. 在 for 循环内的 handleGroupName 处理程序中,它显示错误为:UserDetails.jsx:434 Uncaught TypeError: Cannot read 属性 'getAttribute' of undefined。 3. 我是 React 功能组件的新手,没有太多经验,谁能建议一些更好的方法来从每个渲染的表单字段中获取值,并将它们作为对象合并并存储在主数组中的不同索引处,主数组的结构 groupDetails 定义了它最后的样子。
请试试这个例子,我输入了在组中定义 number of member
的输入。然后显示 number of input groups
(姓名,phone 和性别)。填写信息后,如果您单击 Show
按钮,您将看到结果。
import TextField from "@material-ui/core/TextField";
import React, {useState} from "react";
import Select from "@material-ui/core/Select";
import Button from "@material-ui/core/Button";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Typography from "@material-ui/core/Typography";
export default function DynamicGroupMember() {
const [groupMembersCount, setGroupMembersCount] = useState(0);
const [show, setShow] = useState(false);
const [groupDetails, setGroupDetails] = useState([
{fullName: "", phoneNo: "", gender: ""},
]);
function handleChange(event, index) {
console.log(event.target.value, index);
let newArr = [...groupDetails]; // copying the old datas array
let item = newArr[index];
item = {...item, [event.target.name]: event.target.value};
newArr[index] = item;
setGroupDetails(newArr);
}
return (
<div>
Number of Group: <TextField name="groupMembersCount" onChange={(event) => {
setGroupMembersCount(event.target.value)
}}/>
{Array.apply(null, {length: groupMembersCount}).map(
(e, i) => (
<div key={i}>
<strong>Member #{i + 1}</strong>
<div className="getIndex" name={i + 1}>
<TextField
id={`name${i + 1}`}
name="fullName"
variant="outlined"
margin="none"
label="Name"
onChange={(event) => {
handleChange(event, i)
}}
/>
<TextField
id={`phoneNo${i + 1}`}
name="phoneNo"
variant="outlined"
margin="none"
label="Mobile Number"
onChange={(event) => {
handleChange(event, i)
}}
/>
<Select
id={`gender${i + 1}`}
name="gender"
variant="outlined"
margin="none"
label="Gender"
onChange={(event) => {
handleChange(event, i)
}}
>
<option value="MALE">Male</option>
<option value="FEMALE">Female</option>
<option value="OTHER">Other</option>
</Select>
</div>
</div>
)
)}
<Button onClick={() => {
setShow(true)
}}>Show</Button>
{
show ?
groupDetails.map(member =>
<Card>
<CardContent>
<Typography color="textSecondary" gutterBottom>
{member.fullName}
</Typography>
<Typography variant="h5" component="h2">
{member.phoneNo}
</Typography>
<Typography color="textSecondary">
{member.gender}
</Typography>
</CardContent>
</Card>) : null
}
</div>
);
}