You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

另外还有两个可以优化的小问题:

  1. claves初始状态是数组,但handleChange里按对象更新,类型不一致,建议改成对象初始值:
const [claves, setClaves] = useState({ Pregunta: '', id: 0 });
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:57:34