只允许一个React手风琴同时展开

5

我有一组数据,将用于创建手风琴,我希望只有一个手风琴可以同时展开(例如,如果用户展开手风琴#1,然后展开#2,#1将不再展开)

我有以下代码:

const MyAccordion = props => {
    const [expanded, setExpanded] = React.useState()
    const handleChange = panel => (_, isExpanded) => {setExpanded(isExpanded ? panel : false)}
    const classes = styles //?
    let accordionInfo = createAccordionInfo(props.propthing);
    return (
        <Accordion
            key={accordionInfo.uid}
            onChange={handleChange(accordionInfo.uid)}
            expanded={expanded === accordionInfo.uid}
            TransitionProps={{unmountOnExit: true}}
            className={classes.accordion}
        >
            <AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls={`${accordionInfo.uid}-content`} id={`${accordionInfo.uid}-header`}>
                <Typography>Accordion Summary</Typography>
            </AccordionSummary>

            <AccordionDetails>
                <Typography>Accordion Details</Typography>
            </AccordionDetails>
        </Accordion>
    )
}

const MyAccordions = props => {
    const [expanded, setExpanded] = React.useState()
    const handleChange = panel => (_, isExpanded) => {setExpanded(isExpanded ? panel : false)}
    return (
        <div className={styles.root}>
            {accordions.map(accordion => (
                <MyAccordion onChange={handleChange} propthing={accordion} />
            ))}
        </div>
    )
}

我对 React 还比较陌生,所以我怀疑我的状态设置有误。如有任何帮助或建议,将不胜感激!谢谢

1个回答

9

看起来你试图将状态和处理程序放在父组件 MyAccordions 和子组件 MyAccordion 中。如果你只想打开一个手风琴,那么建议将状态放在父组件中,以便它可以管理打开/展开的内容。使用子手风琴的 id 作为确定应该展开哪个手风琴的基础。

父组件

const MyAccordions = props => {
  const [expanded, setExpanded] = React.useState(null);

  const handleChange = id => (_, isExpanded) => {
    // if expanded, set id to open/expand, close it otherwise 
    setExpanded(isExpanded ? id: null);
  };

  return (
    <div className={styles.root}>
      {accordions.map(accordion => {
        const info = createAccordionInfo(accordion);
        return (
          <MyAccordion
            key={info.uid} // <-- set React key here!!
            onChange={handleChange(info.uid)}
            expanded={expanded === info.uid}
          />
        )
      })}
    </div>
  );
};

子元素

const MyAccordion =({ expanded, onChange }) => {
  const classes = styles //?

  return (
    <Accordion
      onChange={onChange}
      expanded={expanded}
      TransitionProps={{unmountOnExit: true}}
      className={classes.accordion}
    >
      <AccordionSummary
        expandIcon={<ExpandMoreIcon />}
        aria-controls={`${accordionInfo.uid}-content`}
        id={`${accordionInfo.uid}-header`}
      >
        <Typography>Accordion Summary</Typography>
      </AccordionSummary>

      <AccordionDetails>
        <Typography>Accordion Details</Typography>
      </AccordionDetails>
    </Accordion>
  );
};

嗨Drew,感谢您的回复,恐怕手风琴现在完全无法展开 :/ - kougami
@kougami 好的,可能只需要一些微调。你使用哪个组件库,Material-ui吗?你已经有一个运行中的codesandbox或类似的东西可以检查吗? - Drew Reese
1
没问题,我解决了 - 我把 "setExpanded(isExpanded ? null : id);" 改成了 "setExpanded(isExpanded ? id : false);" 然后它就可以工作了。谢谢! :) - kougami
@kougami 啊,你知道吗...那可能是我猜错最多的一行代码,对我来说不清楚 isExpanded 的值代表什么,所以它必须是手风琴所说的应该是什么,而不是它本来的样子。我猜你可以用 null 代替 false,但由于它们都是假值,所以仍然可以工作。对我可能造成的任何困惑表示抱歉。 - Drew Reese
没问题 :) 你是对的,isExpanded应该代表什么不太清楚,但我对React还不是很熟悉。这是我在查看MUI网站上的各种示例后汇总的东西。 - kougami
@kougami 没错,完全正确。既然它似乎暗示着将状态更新为“展开”,那么如果/当您回来重新访问代码时,使用类似shouldExpand这样的名称可能会使含义更加清晰。祝好运。 - Drew Reese

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接