在反应中填充动态呈现的表单字段

Populate dynamically rendered form fields in react

我有 3 个渲染 n 次的 materialUI 文本字段(n 是用户在渲染表单字段之前输入的整数,我将其存储在名为 groupMembersCount 的变量中)。 我正在通过这种方式动态渲染它:

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>
    );
}

如果我填写了数字 (groupMembersCount) 然后填写了那些表单字段并在填写后修改了 groupMembersCount (增加或减少),如果增加,我希望用户填写的值应该保留,如果减少,表单字段值应该清除。 我尝试将 groupDetails 数组中的值传递到 "value" prop 中,但它显示错误,因为索引 I 和 writing/passing 值最初在该索引处不存在。

您需要使用 useState 之前存储的 groupDetails 中的设置值。请检查此示例:

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 DynamicGroupMember3() {
    const [groupMembersCount, setGroupMembersCount] = useState(0);
    const [show, setShow] = useState(false);
    const [errorText, setErrorText] = useState([]);
    const [showState, setShowState] = useState(false);
    const [groupDetails, setGroupDetails] = useState([
        {fullName: "", phoneNo: "", gender: ""},
    ]);
    const [state, setState] = React.useState({
        idProof: "",
        noOfPeople: "",
        bookingId: "",
        detailsOfPeople: [],
    });

    function handleChange(event, index) {
        event.preventDefault();
        console.log(errorText.length, 'length');
        if (event.target.name === "phoneNo") {
            // do validation here
            let valid = false;
            if (isNaN(event.target.value)) {
                let arr = [...errorText];
                arr[index] = 'Invalid ' + event.target.name;
                setErrorText(arr);
            } else {
                let arr = [...errorText];
                arr[index] = '';
                setErrorText(arr);
            }
        }

        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) => {
            if (isNaN(event.target.value)) {
                alert('Please enter number');
                return;
            }
            if (event.target.value !== '') {
                let noOfMember = parseInt(event.target.value);
                let errors = new Array(noOfMember);
                setErrorText(errors);
                if (groupMembersCount > noOfMember) {
                    let newGroup = [];
                    groupDetails.map((group, index) => {
                        if (index < noOfMember) {
                            newGroup.push(group);
                        }
                    });
                    setGroupDetails(newGroup);
                }
                setGroupMembersCount(noOfMember);
            }
        }}/>
            {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"
                                value={groupDetails[i] ? groupDetails[i].fullName : ''}
                                onChange={(event) => {
                                    handleChange(event, i)
                                }}
                            />
                            <TextField
                                id={`phoneNo${i + 1}`}
                                name="phoneNo"
                                variant="outlined"
                                margin="none"
                                label="Mobile Number"
                                value={groupDetails[i] ? groupDetails[i].phoneNo : ''}
                                onChange={(event) => {
                                    handleChange(event, i)
                                }}
                                error={errorText[i] !== '' && errorText[i] !== undefined}
                                helperText={errorText[i]}
                            />
                            <Select
                                id={`gender${i + 1}`}
                                name="gender"
                                variant="outlined"
                                margin="none"
                                label="Gender"
                                value={groupDetails[i] ? groupDetails[i].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, index) =>
                        <Card key={index}>
                            <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
            }
            <Button onClick={() => {
                console.log(groupDetails, 'groupDetails');
                setState({
                    idProof: "XYZ123",
                    noOfPeople: groupDetails.length,
                    bookingId: "boking-4434",
                    detailsOfPeople: groupDetails
                });
                console.log(groupDetails, 'groupDetails');
                setShowState(true);

            }}>Show STATE</Button>
            {
                showState ?
                    <Card>
                        <CardContent>
                            <Typography color="textSecondary" gutterBottom>
                                Id Proof: {state.idProof}
                            </Typography>
                            <Typography variant="h5" component="h2">
                                No Of People: {state.noOfPeople}
                            </Typography>
                            <Typography color="textSecondary">
                                Booking Id: {state.bookingId}
                            </Typography>
                        </CardContent>
                    </Card> : null
            }
        </div>
    );
}