如何为多个Collapse创建动态状态

3

我需要从数组数据中创建折叠菜单,但现在我点击任何菜单都会展开所有子菜单。

我认为问题出在我无法为主菜单设置唯一的“打开”状态。

我不希望分配“状态”,以支持将来可能有3个或4个附加数据的情况。

我使用React.js和material-ui。

请帮帮我,非常感谢。

const myData = [
  {
    id: '1',
    nameHeader: 'Header1',
    subMenu: [{ id: '1', name: 'subMenu1' }, { id: '2', name: 'subMenu2' }]
  },
  {
    id: '2',
    nameHeader: 'Header2',
    subMenu: [{ id: '1', name: 'subMenu1' }, { id: '2', name: 'subMenu2' }]
  }
]

class Myclass extends Component {
  state = { open: false }

  handleClick = () => {
    this.setState(state => ({ open: !state.open }))
  }

  render() {
    const { open } = this.state
    return (
      <div style={{ marginRight: '15px' }}>
        <List component="nav">
          {myData.map(each => (
            <React.Fragment key={each.id}>
              <ListItem button onClick={this.handleClick}>
                <ListItemText inset primary={each.nameHeader} />
                {open ? <ExpandLess /> : <ExpandMore />}
              </ListItem>
              <Divider />
              <Collapse in={open} timeout="auto" unmountOnExit>
                <List component="div" disablePadding>
                  {each.subMenu.map(subData => (
                    <ListItem key={subData.id} button>
                      <ListItemText inset primary={subData.name} />
                    </ListItem>
                  ))}
                </List>
              </Collapse>
            </React.Fragment>
          ))}
        </List>
      </div>
    )
  }
}
export default Myclass
1个回答

7
我认为我的问题是我不能为主菜单设置唯一的状态“打开”。
某种程度上,是的。您有两个不同的(子)菜单,您想折叠/展开它们而不对其他菜单产生影响。考虑到这一点,您需要创建一个可能性来分别保存每个菜单的当前“打开”状态。
您已经为不同的菜单拥有唯一的ID,可以使用它们来实现您的目标。其中一种方法是将状态与菜单的相关设置扩展:
state = { settings: [{ id: "1", open: false }, { id: "2", open: false }] };

这样可以让您了解每个菜单的折叠状态信息。
根据这一点,您需要稍微扩展handleClick函数,以便仅更改您单击的菜单项的状态。
handleClick = id => {
  this.setState(state => ({
    ...state,
    settings: state.settings.map(item =>
      item.id === id ? { ...item, open: !item.open } : item
    )
  }));
};

在您的渲染函数中,您需要确保将您所点击的菜单项的正确id传递给handleClick函数,并选择正确的打开状态。

<React.Fragment key={each.id}>
  <ListItem button onClick={() => this.handleClick(each.id)}>
    <ListItemText inset primary={each.nameHeader} />
    settings.find(item => item.id === each.id).open
    ? "expanded"
    : "collapsed"}
  </ListItem>
  <Divider />
  <Collapse
    in={settings.find(item => item.id === each.id).open}
    timeout="auto"
    unmountOnExit
  >
  <List component="div" disablePadding>
    {each.subMenu.map(subData => (
      <ListItem key={subData.id} button>
        <ListItemText inset primary={subData.name} />
      </ListItem>
     ))}
   </List>
 </Collapse>
</React.Fragment>

看这里演示效果:https://codesandbox.io/s/6xjz837j9z

改进后的handleClick函数。 :) - grenzbotin
感谢您的帮助。 我的意思是,如果我不想被分配状态。 为了支持未来可能有3或4个额外菜单的其他数据,我需要做什么? - Panudeth Jaruwong
你的菜单数据将来自哪里?我想它来自props。在“MyClass”组件被挂载的时候,你可以相应地定义你的状态:对于每个菜单,你可以在设置数组中创建一个对象,让你控制每个菜单的折叠状态。 - grenzbotin

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