React中如何将Respuesta列表垂直渲染而非并排显示?
React + Material UI 渲染问题:Respuesta数组无法垂直排列
我用React和Material UI开发时碰到个渲染问题:已经给两个TextField设置了onChange来维护claves和valores状态,点击“Agregar”按钮会把这些状态保存到guardar状态,然后在Material UI的Accordion里渲染。现在Pregunta能正常渲染,但Respuesta数组渲染时是并排显示的,我想让它们像<li>标签那样每个占一行垂直排列,试了好几种方法都没解决。
组件逻辑代码
const [claves, setClaves] = useState([{ Pregunta: '' }]); const [valores, setValores] = useState([{ Respuesta: '' }]); const [count, setCount] = useState(0); const [guardar, setGuardar] = React.useState([{ Pregunta: '', Respuesta: [], Counter: 0 }]); const [expanded, setExpanded] = React.useState(false); const handleChangeInput = (e, i) => { const { name, value } = e.target; const lista = [...valores]; lista[i][name] = value; setValores(lista); }; const handleChange = (e) => { setClaves({ ...claves, [e.target.name]: e.target.value, id: claves.id + 1, }); console.log(claves); }; const handleAddFields = () => { setValores([...valores, { Respuesta: '' }]); }; const handleRemoveFields = (i) => { const lista = [...valores]; lista.splice(i, 1); setValores(lista); }; const handleChangePanel = (panel) => (event, isExpanded) => { setExpanded(isExpanded ? panel : false); }; const handleSave = () => { console.log('enviar'); }; const handleSubmit = (e) => { e.preventDefault(); setGuardar([ ...guardar, { Pregunta: claves.Pregunta, Respuesta: valores.map((el) => el.Respuesta), Counter: count, }]); const counter = count + 1; const panels = `panel${counter}`; setCount(panels); setClaves({ Pregunta: '' }); setValores([{ Respuesta: '' }]); };
渲染代码
return ( <Grid container spacing={2} columns={2}> <Grid item xs={5}> <form className={classes.root} onSubmit={handleSubmit}> <TextField name="Pregunta" label="Pregunta" variant="outlined" value={claves.Pregunta} onChange={handleChange} /> { valores.map((valor, i) => ( // eslint-disable-next-line react/no-array-index-key <div key={i}> <TextField name="Respuesta" label="Respuesta" variant="outlined" value={valor.Respuesta} onChange={(e) => handleChangeInput(e, i)} /> <IconButton disabled={valores.length === 1} onClick={() => handleRemoveFields(i)} > - </IconButton> <IconButton onClick={handleAddFields} > + </IconButton> </div> )) } <Button className={classes.button} variant="contained" color="primary" type="submit" onClick={handleSubmit} > Agregar </Button> </form> </Grid> <Grid xs={1}> <Paper style={{ maxHeight: 1000, width: 500, overflow: 'auto' }}> {guardar.map((el) => ( <Accordion expanded={expanded === el.Counter} onChange={handleChangePanel(el.Counter)}> <AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls="panel1bh-content" id="panel1bh-header" > <Typography sx={{ width: '33%', flexShrink: 0 }}> {el.Pregunta} </Typography> </AccordionSummary> <AccordionDetails> <ul> <li>{el.Respuesta}</li> </ul> </AccordionDetails> </Accordion> ))} <Button onClick={handleSave}>registrar</Button> </Paper> </Grid> </Grid> ); }
测试遍历的代码
let perro = { nombre: "Scott", color: "Negro", macho: true, edad: 5 }; for (let clave in perro){ console.log(perro[clave]); } /* "Scott" "Negro" true 5 */
解决方案
问题核心是你把整个Respuesta数组直接塞到一个<li>里,React会默认把数组元素用逗号分隔并排显示。要实现每个选项占一行,需要遍历Respuesta数组,为每个元素生成独立的<li>标签。
修改AccordionDetails中的代码:
<AccordionDetails> <ul> {el.Respuesta.map((respuesta, index) => ( <li key={index}>{respuesta}</li> ))} </ul> </AccordionDetails>
另外还有两个可以优化的小问题:
claves初始状态是数组,但handleChange里按对象更新,类型不一致,建议改成对象初始值:
const [claves, setClaves] = useState({ Pregunta: '', id: 0 });
count的类型从数字变成字符串,逻辑混乱,建议统一用数字:
const handleSubmit = (e) => { e.preventDefault(); const newCount = count + 1; setGuardar([ ...guardar, { Pregunta: claves.Pregunta, Respuesta: valores.map((el) => el.Respuesta), Counter: newCount, }]); setCount(newCount); setClaves({ Pregunta: '', id: newCount }); setValores([{ Respuesta: '' }]); };
内容的提问来源于stack exchange,提问作者lucas Casco
相关产品推荐
相关产品推荐

