Populate dynamically rendered form fields in react

拥有回忆 提交于 2020-06-17 09:37:07

问题


I am having 3 materialUI TextFields which are render n number of times (n is an integer input from the user before rendering the form field, where I stored it in a variable named groupMembersCount). I am getting it dynamically rendered by this way:

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

What if I filled the number (groupMembersCount) and then filled those form fields and after filling, I modified groupMembersCount (either increase or decrease), in case of increase I want the values that user filled should retain and if decreased, form fields values should clear out. I tried passing values from groupDetails array to form in "value" prop but it shows an error because the index I an writing/passing the values initially doesn't exist at that index.


回答1:


You need set value from groupDetails that was stored before using useState. Please check this example:

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


来源:https://stackoverflow.com/questions/62121702/populate-dynamically-rendered-form-fields-in-react

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!