React JS中如何动态添加嵌套子数组输入字段 单section支持多视频行
实现方案
你需要新增针对单个section添加视频输入对的处理逻辑,同时调整JSX渲染结构新增对应操作按钮即可,具体修改如下:
1. 新增视频操作处理函数
在组件中新增两个函数(删除单组视频为可选优化,满足至少保留1组视频的常用需求):
// 给指定section新增一组视频输入 const handleAddVideoField = (sectionIndex) => { const newSectionFields = [...sectionFields]; newSectionFields[sectionIndex].videoContents.push({ videoName: '', videoUrl: '' }); setSectionFields(newSectionFields); }; // 可选:删除指定section下的某组视频输入,至少保留1组 const handleRemoveVideoField = (sectionIndex, videoIndex) => { const newSectionFields = [...sectionFields]; newSectionFields[sectionIndex].videoContents.splice(videoIndex, 1); // 防止视频组被全部删除 if (newSectionFields[sectionIndex].videoContents.length === 0) { newSectionFields[sectionIndex].videoContents.push({ videoName: '', videoUrl: '' }); } setSectionFields(newSectionFields); };
2. 调整JSX渲染结构
在视频输入对的位置新增操作按钮,同时你原有代码中函数名拼写Chang应为Change,同步修正即可:
修改后的视频渲染部分代码:
{inputField?.videoContents?.map((v, i) => ( <div key={i} style={{ display: 'flex', alignItems: 'center', marginLeft: '24px' }}> <TextField name="videoName" label="Enter Video Name" variant="filled" value={v.videoName} onChange={event => handleChangeVideoInput(index, i, event)} /> <TextField name="videoUrl" label="Enter Video Url" variant="filled" value={v.videoUrl} onChange={event => handleChangeVideoInput(index, i, event)} /> {/* 当前section下新增视频组的加号按钮 */} <IconButton onClick={() => handleAddVideoField(index)}> <AddIcon /> </IconButton> {/* 可选:删除当前视频组的减号按钮,仅当视频组数量大于1时显示 */} {inputField.videoContents.length > 1 && ( <IconButton onClick={() => handleRemoveVideoField(index, i)}> <RemoveIcon /> </IconButton> )} </div> ))}
完整修改后代码
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: '' }] }]) // 修正原拼写错误 Chang => Change function handleChangeInput(index, event) { const values = [...sectionFields]; values[index][event.target.name] = event.target.value; setSectionFields(values); } // 修正原拼写错误 Chang => Change function handleChangeVideoInput(index, i, event) { const values = [...sectionFields]; values[index].videoContents[i][event.target.name] = event.target.value; setSectionFields(values); } 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: ''}] }]) } // 给指定section新增一组视频输入 const handleAddVideoField = (sectionIndex) => { const newSectionFields = [...sectionFields]; newSectionFields[sectionIndex].videoContents.push({ videoName: '', videoUrl: '' }); setSectionFields(newSectionFields); }; // 可选:删除指定section下的某组视频输入,至少保留1组 const handleRemoveVideoField = (sectionIndex, videoIndex) => { const newSectionFields = [...sectionFields]; newSectionFields[sectionIndex].videoContents.splice(videoIndex, 1); // 防止视频组被全部删除 if (newSectionFields[sectionIndex].videoContents.length === 0) { newSectionFields[sectionIndex].videoContents.push({ videoName: '', videoUrl: '' }); } setSectionFields(newSectionFields); }; 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 => handleChangeInput(index, event)} /> <TextField name="overview" label="Section Overview" variant="filled" value={inputField?.overview} onChange={event => handleChangeInput(index, event)} /> <IconButton onClick={() => handleRemoveFields(index)}> <RemoveIcon/> </IconButton> <IconButton onClick={handleAddFields}> <AddIcon/> </IconButton> {inputField?.videoContents?.map((v, i) => ( <div key={i} style={{ display: 'flex', alignItems: 'center', marginLeft: '24px', marginTop: '8px' }}> <TextField name="videoName" label="Enter Video Name" variant="filled" value={v.videoName} onChange={event => handleChangeVideoInput(index, i, event)} /> <TextField name="videoUrl" label="Enter Video Url" variant="filled" value={v.videoUrl} onChange={event => handleChangeVideoInput(index, i, event)} /> {/* 当前section下新增视频组的加号按钮 */} <IconButton onClick={() => handleAddVideoField(index)}> <AddIcon /> </IconButton> {/* 可选:删除当前视频组的减号按钮,仅当视频组数量大于1时显示 */} {inputField.videoContents.length > 1 && ( <IconButton onClick={() => handleRemoveVideoField(index, i)}> <RemoveIcon /> </IconButton> )} </div> ))} </div> ))} <Button className={classes.button} variant='contained' color='primary' type='submit' endIcon={<Icon/>} onClick={handleSubmit} > SEND </Button> </form> </Container> </div> ); } export default CreateCourse;
修改后原section旁的加号按钮功能保持不变,点击仍新增完整section行;每组视频输入旁的加号点击后只会在当前section下新增一组视频输入对,符合需求。
内容的提问来源于stack exchange,提问作者Partho
相关产品推荐
相关产品推荐

