首页 > 解决方案 > 如何在 React JS 中动态添加子数组输入字段

问题描述

这是我的代码

const useStyles = makeStyles((theme) => ({
root: {
    '& .MuiTextField-root': {
        margin: theme.spacing(1)
    },
},
button: {
    margin: theme.spacing(1)
}
}))

function CreateCourse() {

const classes = useStyles();
const [sectionFields, setSectionFields] = useState([{
    sectionName: '',
    overview: '',
    videoContents: [{
        videoName: '', videoUrl: ''
    }]
}])

function handleChangInput(index, event) {
    const values = [...sectionFields];
    values[index][event.target.name] = event.target.value;
    setSectionFields(values);
}

function handleChangVideoInput(index, i, event) {
    const values = [...sectionFields];
    values[index].videoContents[i][event.target.name] = event.target.value;
    setSectionFields(values);
    console.log(index, event.target.name)
}


const handleSubmit = (event) => {
    event.preventDefault();
    console.log("Input Field ", sectionFields)
}

const handleRemoveFields = (index) => {
    const values = [...sectionFields];
    values.splice(index, 1)
    setSectionFields(values)
}

const handleAddFields = () => {
    setSectionFields([...sectionFields, {
        sectionName: '',
        overview: '',
        videoContents: [{videoName: '', videoUrl: ''}]
    }])
}

return (
    <div className='container mb-5'>
        <Container>
            <h1>Add New Member</h1>
            <form className={classes.root} onSubmit={handleSubmit}>
                {sectionFields.map((inputField, index) => (
                    <div key={index}>
                        <TextField
                            name="sectionName"
                            label="Section Name"
                            variant="filled"
                            value={inputField?.sectionName}
                            onChange={event => handleChangInput(index, event)}
                        />
                        <TextField
                            name="overview"
                            label="Section Overview"
                            variant="filled"
                            value={inputField?.overview}
                            onChange={event => handleChangInput(index, event)}
                        />

                        <IconButton onClick={() => handleRemoveFields(index)}>
                            <RemoveIcon/>
                        </IconButton>
                        <IconButton onClick={handleAddFields}>
                            <AddIcon/>
                        </IconButton>

                        {inputField?.videoContents?.map((v, i) => (
                            <div key={i}>
                                <TextField
                                    name="videoName"
                                    label="Enter Video Name"
                                    variant="filled"
                                    value={v.videoName}
                                    onChange={event => handleChangVideoInput(index, i, event)}
                                />
                                <TextField
                                    name="videoUrl"
                                    label="Enter Video Url"
                                    variant="filled"
                                    value={v.videoUrl}
                                    onChange={event => handleChangVideoInput(index, i, event)}
                                />
                                
                            </div>
                        ))}
                    </div>
                ))}
                <Button
                    className={classes.button}
                    variant='contained'
                    color='primary'
                    type='submit'
                    endIcon={<Icon/>}
                    onClick={handleSubmit}
                >
                    SEND
                </Button>
            </form>
        </Container>
    </div>

);
}
export default CreateCourse;

屏幕截图中的输出

在此处输入图像描述

当我单击加号图标时,会创建一个新输入,例如

在此处输入图像描述

但是我想要一个 sectionName 有很多 videoName 和 videoUrl 就像我想在 videoUrl 一侧创建加号图标,当用户单击加号图标时,它会根据用户的需要创建许多 videoName 和 videoUrl,如果用户单击部分,那么它会创建一个部分行一个视频行。如何使用反应解决这个问题?

标签: javascriptarraysreactjsreact-hooks

解决方案


首先,当您使用状态的当前值来计算新的状态值时,最好使用回调函数。这样它就不会受到重新渲染的影响,并保证计算使用最新的状态值。

所以假设你有

const [state, setState] = useState([]);

不要使用:

const next = [...state, newElement];
setState(next);

但是,请使用:

setState((previous) => [...previous, newElement]);

为了将更多字段添加到嵌套数组中,您可以像这样更新状态:

function addToSection(i) {
  setSectionFields((prev) => (
    const updatedSection = {
      ...prev[i],
      videoContents: [
        ...prev[i].videoContents,
        { videoName: '', videoUrl: '' },
      ],
    };
    return prev.map((section, index) => {
      return index === i ? updatedSection : section;
    });
  );
}

推荐阅读