使用递归渲染的材质UI嵌套列表不适用于react钩子

时间:2019-11-30 09:20:18

标签: reactjs material-ui react-hooks

我正在一个项目中,我需要一个带有使用材料UI创建的嵌套列表的边栏,如果我要演示并复制嵌套列表代码,一切都很好,但是它带有很多代码重复。因此,经过一番挖掘,我发现了用类编写的递归渲染函数gist。我正在使用反应挂钩,并且函数逻辑无法按预期工作。

问题: 我有3级导航,一个父级,然后子级和子级包含更多项(孙子级到父级)。因此,当我单击父项时,将显示所有很好的子项,但是当我单击任何子项元素时,整个列表将关闭。

这是我的代码:

// useState hook with empty object as an initial Value

const [open1, setOpen1] = React.useState({});

// this method sets the current state of a menu item i.e whether it is in expanded or collapsed or a collapsed state

const handleClick = (param) => {
        setOpen1(prevState => ({[param]: !prevState[param]}));
    };

// if the menu item doesn't have any child, this method simply returns a clickable menu item that redirects to any location and if there is no child this method uses recursion to go until the last level of children and then returns the item by the first condition.

function nestedMenu(items) {

        return items.map((nav) => {
            if (!nav.children) {
                return (
                    <div key={nav.id}>
                        <ListItem button>
                            <ListItemText primary={nav.name} />
                        </ListItem>
                    </div>
                )
            }
            return (
                <div key={nav.id}>
                    <ListItem button onClick={()=>handleClick(nav.name)}>
                        <ListItemText primary={nav.name} />
                        {open1[nav.name] ? <ExpandLess /> : <ExpandMore />}
                    </ListItem>
                    <Collapse in={open1[nav.name] } timeout="auto" unmountOnExit>
                        <List component="div" disablePadding>
                          { nestedMenu(nav.children)}
                        </List>
                    </Collapse>
                </div>
            )
        })
    }

此后,我在返回方法中以json数据为参数调用nestedMenu函数

<List> {nestedMenu(Links.items)} </List>

任何人都可以解释一下我在这方面做错了什么,我一直在努力找出问题所在。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

问题是您更改了整个open1对象:

const handleClick = (param) => {
      setOpen1(prevState => ({[param]: !prevState[param]}));
};

例如,如果您有{p1:true, p2:false}并执行handkeClick('p1'), open1将为{p1:false}。 您需要保持open1的其他成员不变,而只更新您想要的成员:

const handleClick = (param) => {
      setOpen1(prevState => 
          retrun {...prevState ,[param]: !prevState[param]}
      );
};