反应钩子 setState 没有正确地重新渲染组件



我有一个组件(切换菜单列表(,它应该在单击按钮时加载一个子组件(切换菜单项(。

这是它的工作原理。

'btnId' 初始化状态 = 空

->按钮点击

->将状态更新为索引号 1

-> (btnId !== null( && 加载子组件

但是,子组件不会在状态更新时显示。

如果我将初始化状态设置为 1,它会在单击按钮时显示。

切换菜单列表.js

import React, { useState, useRef } from 'react';
import Button from '@material-ui/core/Button';
import { withStyles } from '@material-ui/core/styles';
/* --- Components --- */
import Loader from '../../shared/loader';
const ToggleMenuItems = Loader({
  loader: () =>
    import('./toggleMenuItems' /* webpackChunkName: 'ToggleMenuItems' */),
});
const styles = theme => ({
...
});
const ToggleMenuList = ({ navAdminList, navAdminItems, classes }) => {
  const [open, setOpen] = useState(false);
  const [btnId, setBtnId] = useState(null);
  const anchorRef = useRef(null);
  const handleToggle = async id => {
    await setBtnId(id);
    return setOpen(prevOpen => !prevOpen);
  };
  const handleClose = event => {
   ...
  };
  console.log('Toggle Menu List is rendered');
  console.log('btnId: ', btnId);
  return (
    <React.Fragment>
      <div className={`nav-menu ${classes.root}`}>
        {navAdminList.map(e => (
          <Button
            key={e.id}
            ref={anchorRef}
            aria-owns={open ? 'menu-list-grow' : undefined}
            aria-haspopup="true"
            onClick={() => handleToggle(e.id)}
            className={e.className}
          >
            {e.name}
          </Button>
        ))}
      </div>
      {btnId !== null && (
        <ToggleMenuItems
          handleClose={handleClose}
          open={open}
          anchorRef={anchorRef}
          items={navAdminItems[btnId]}
        />
      )}
    </React.Fragment>
  );
};
export default withStyles(styles)(ToggleMenuList);

切换菜单项.js

const ToggleMenuItems = ({ handleClose, open, anchorRef, items }) => {
  console.log('Toggle Menu Items is rendered.');
  console.log('open: ', open);
  return (
    <Popper
      open={open}
      anchorEl={anchorRef.current}
      keepMounted
      transition
      disablePortal
    >
      {({ TransitionProps, placement }) => (
        <Grow
          {...TransitionProps}
          style={{
            transformOrigin:
              placement === 'bottom' ? 'center top' : 'center bottom',
          }}
        >
          <Paper id="menu-list-grow">
            <ClickAwayListener onClickAway={handleClose}>
              <MenuList>
                {items.map(e => (
                  <MenuItem key={e.id} onClick={handleClose}>
                    <Link to={e.to} className={e.className}>
                      {e.name}
                    </Link>
                  </MenuItem>
                ))}
              </MenuList>
            </ClickAwayListener>
          </Paper>
        </Grow>
      )}
    </Popper>
  );
};
export default ToggleMenuItems;

这是我得到的控制台日志。

* On page load
toggleMenuList.js:  Toggle Menu List is rendered
toggleMenuList.js:  btnId:  null
* On button click
toggleMenuList.js:  Toggle Menu List is rendered
toggleMenuList.js:  btnId:  1
toggleMenuList.js:  Toggle Menu List is rendered
toggleMenuList.js:  btnId:  1
toggleMenuItems.js: Toggle Menu Items is rendered.
toggleMenuItems.js: open: true

结果

  • 状态值已更新。

  • 子组件似乎已加载。(控制台.log被解雇(

  • 但它不显示。

我用不同的方法解决了这个问题。我使用初始值"null"设置 activeId 状态,该状态在单击按钮时以"单击的按钮 id"更新。并且仅当"按钮 Id"与"activeId"匹配时加载子组件。

我还在子组件中添加了这个条件。

const isOpen = activeId === id;
  return (
    <Popper
      open={isOpen}

这样,当一个按钮打开为真时,其余按钮设置为 false。

切换菜单列表.js

const ToggleMenuList = ({ navAdminList, navAdminItems, classes }) => {
  const [activeId, setActiveId] = useState(null);
  const anchorRef = useRef(null);
  const handleToggle = id => {
    setActiveId(id);
  };
  const handleClose = (event) => {
    if (anchorRef.current && anchorRef.current.include(event.target)) {
      return;
    }
    setActiveId(null);
  };
  return (
    <React.Fragment>
      <div className={`nav-menu ${classes.root}`}>
        {navAdminList.map(e => (
          <div key={e.id}>
            <Button
              ref={anchorRef}
              aria-owns={activeId === e.id ? 'menu-list-grow' : undefined}
              aria-haspopup="true"
              onClick={() => handleToggle(e.id)}
              className={e.className}
            >
              {e.name}
            </Button>
            {activeId === e.id && (
              <ToggleMenuItems
                id={e.id}
                activeId={activeId}
                handleClose={handleClose}
                anchorRef={anchorRef}
                items={navAdminItems[e.id]}
              />
            )}
          </div>
        ))}
      </div>
    </React.Fragment>
  );
};

切换菜单项.js

const ToggleMenuItems = ({ id, activeId, handleClose, anchorRef, items }) => {
  const isOpen = activeId === id;
  return (
    <Popper
      open={isOpen}
      anchorEl={anchorRef.current}
      keepMounted
      transition
      disablePortal
    >
      {({ TransitionProps, placement }) => (
        <Grow
          {...TransitionProps}
          style={{
            transformOrigin:
              placement === 'bottom' ? 'center top' : 'center bottom',
          }}
        >
          <Paper id="menu-list-grow">
            <ClickAwayListener onClickAway={() => handleClose(id)}>
              <MenuList>
                {items.map(e => (
                  <MenuItem key={e.id} onClick={() => handleClose(id)}>
                    <Link to={e.to} className={e.className}>
                      {e.name}
                    </Link>
                  </MenuItem>
                ))}
              </MenuList>
            </ClickAwayListener>
          </Paper>
        </Grow>
      )}
    </Popper>
  );
};

相关内容

  • 没有找到相关文章

最新更新