首页 > 解决方案 > React Hooks:无法识别汉堡菜单onClick的useCallback返回值

问题描述

我的应用程序中有一个组件可以处理两件事,

应用程序的布局(移动与桌面)以及其中的导航。这是一个类实现。

import React, { Component, createRef } from 'react';
import { Link, NavLink } from 'react-router-dom';
import Modal from '../components/Modal/MyModal.jsx';
import {
  Container,
  Menu,
  Responsive,
  Segment,
  Visibility,
  Sidebar,
  Icon,
  Button
} from 'semantic-ui-react';

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { modalStateOn, modalStateOff } from '../store/reducers/ui/index';
import { loadAvatar } from '../store/reducers/users/index';

const getWidth = () => {
  const isSSR = typeof window === 'undefined';

  return isSSR ? Responsive.onlyTablet.minWidth : window.innerWidth;
};

const logOutMenuItemHelper = (
  isMobile,
  isLoggedIn,
  history,
  modalActive,
  nav,
  NavLink,
  modalStateOn,
  modalStateOff,
  handleSidebarHide
) => {
  function mobilelogOutMenuItemHelper(
    history,
    modalActive,
    nav,
    NavLink,
    modalStateOn,
    handleSidebarHide
  ) {
    if (nav.name === 'Log in') {
      console.log('mobile nav.name ', nav.name);

      return (
        <React.Fragment key={'modalForMobile'}>
          {modalActive && (
            <Modal
              isAlertModal={false}
              history={history}
              affirmativeUsed="Yes"
              message=" Are you sure you want to log out of your account?"
              modalActive={modalActive}
            />
          )}
          <Menu.Item
            key={'modalForMobile'}
            name="Log out"
            onClick={event => {
              modalStateOn();
              handleSidebarHide();
            }}
          >
            Log Out
          </Menu.Item>
        </React.Fragment>
      );
    } else {
      return (
        <Menu.Item
          exact
          key={nav.name}
          as={NavLink}
          to={nav.path}
          name={nav.name}
          onClick={() => {
            handleSidebarHide();
          }}
        />
      );
    }
  }

  function desktoplogOutMenuItemHelper(
    history,
    modalActive,
    nav,
    NavLink,
    modalStateOn,
    modalStateOff
  ) {
    if (nav.name === 'Log in') {
      return (
        <React.Fragment key={'modalForDesktop'}>
          {modalActive && (
            <Modal
              isAlertModal={false}
              history={history}
              affirmativeUsed="Yes"
              message="Are you sure you want to log out of your account?"
              modalActive={modalActive}
            />
          )}
          <Menu.Item
            key={'modalForDesktop'}
            name="Log out"
            onClick={event => {
              modalStateOn();
            }}
          >
            Log Out
          </Menu.Item>
        </React.Fragment>
      );
    } else {
      return (
        <Menu.Item exact key={nav.name} as={NavLink} to={nav.path} name={nav.name} />
      );
    }
  }

  if (isMobile && isLoggedIn) {
    return mobilelogOutMenuItemHelper(
      history,
      modalActive,
      nav,
      NavLink,
      modalStateOn,
      modalStateOff,
      handleSidebarHide
    );
  }
  return desktoplogOutMenuItemHelper(
    history,
    modalActive,
    nav,
    NavLink,
    modalStateOn,
    modalStateOff
  );
};

class DesktopContainer extends Component {
  state = {};

  hideFixedMenu = () => this.setState({ fixed: false });
  showFixedMenu = () => this.setState({ fixed: true });

  render() {
    const { fixed } = this.state;
    const {
      history,
      data,
      children,
      isLoggedIn,
      modalActive,
      modalStateOn,
      modalStateOff
    } = this.props;
    // console.log("this.props desktop in LinkNAV ", this.props);
    return (
      <Responsive getWidth={getWidth} minWidth={Responsive.onlyTablet.minWidth}>
        <Visibility
          once={false}
          onBottomPassed={this.showFixedMenu}
          onBottomPassedReverse={this.hideFixedMenu}
        >
          <Segment
            inverted
            textAlign="center"
            style={{ minHeight: 'auto', padding: '0' }}
            vertical
          >
            <Menu
              fixed={fixed ? 'top' : null}
              inverted={!fixed}
              pointing={!fixed}
              secondary={!fixed}
              size="large"
            >
              {/* {console.log("isLoggedIn in desktop homecomponent ", isLoggedIn)} */}
              {isLoggedIn
                ? data
                    .filter(function(nav) {
                      return nav.name !== 'Register';
                    })
                    .map(nav => {
                      return logOutMenuItemHelper(
                        false,
                        isLoggedIn,
                        history,
                        modalActive,
                        nav,
                        NavLink,
                        modalStateOn,
                        modalStateOff
                      );
                    })
                : data
                    .filter(function(nav) {
                      return nav.name != 'Profile' && nav.name != 'Dashboard';
                    })
                    .map(nav => {
                      return (
                        <Menu.Item
                          exact
                          key={nav.path}
                          as={NavLink}
                          to={nav.path}
                          name={nav.name}
                        />
                      );
                    })}
            </Menu>
          </Segment>
        </Visibility>
        {children}
      </Responsive>
    );
  }
}

class MobileContainer extends Component {
  state = {};

  handleSidebarHide = () => this.setState({ sidebarOpened: false });

  handleToggle = () => this.setState({ sidebarOpened: true });

  render() {
    const {
      children,
      history,
      data,
      isLoggedIn,
      modalActive,
      modalStateOn,
      modalStateOff
    } = this.props;
    const { sidebarOpened } = this.state;

    return (
      <Responsive
        as={Sidebar.Pushable}
        getWidth={getWidth}
        maxWidth={Responsive.onlyMobile.maxWidth}
      >
        <Sidebar
          as={Menu}
          animation="push"
          inverted
          onHide={this.handleSidebarHide}
          vertical
          visible={sidebarOpened}
        >
          {isLoggedIn
            ? data
                .filter(function(nav) {
                  return nav.name !== 'Register';
                })
                .map(nav => {
                  return logOutMenuItemHelper(
                    false,
                    isLoggedIn,
                    history,
                    modalActive,
                    nav,
                    NavLink,
                    modalStateOn,
                    modalStateOff,
                    this.handleSidebarHide
                  );
                })
            : data
                .filter(function(nav) {
                  return nav.name != 'Profile' && nav.name != 'Dashboard';
                })
                .map(nav => {
                  return (
                    <Menu.Item
                      exact
                      key={nav.name}
                      as={NavLink}
                      to={nav.path}
                      name={nav.name}
                      onClick={this.handleSidebarHide}
                    />
                  );
                })}
        </Sidebar>

        <Sidebar.Pusher dimmed={sidebarOpened}>
          <Segment
            inverted
            textAlign="center"
            style={{ minHeight: 'auto', padding: '1em 0em' }}
            vertical
          >
            <Container>
              <Menu inverted pointing secondary size="large">
                <Menu.Item onClick={this.handleToggle}>
                  <Icon name="sidebar" />
                </Menu.Item>
                <Menu.Item position="right">
                  <Button inverted>
                    {isLoggedIn ? (
                      <Link to="/">Log out</Link>
                    ) : (
                      <Link to="/login">Log in</Link>
                    )}
                  </Button>
                  {!isLoggedIn ? (
                    <Button inverted style={{ marginLeft: '0.5em' }}>
                      <Link to="/register">
                        <span>Register!</span>
                      </Link>
                    </Button>
                  ) : null}
                </Menu.Item>
              </Menu>
            </Container>
          </Segment>

          {children}
        </Sidebar.Pusher>
      </Responsive>
    );
  }
}

const LinkNavWithLayout = ({
  children,
  history,
  data,
  userAvatar,
  modalActive,
  modalStateOn,
  modalStateOff,
  isLoggedIn
}) => (
  <React.Fragment>
    <DesktopContainer
      history={history}
      data={data}
      userAvatar={userAvatar}
      modalActive={modalActive}
      modalStateOn={modalStateOn}
      modalStateOff={modalStateOff}
      isLoggedIn={isLoggedIn}
    >
      {children}
    </DesktopContainer>
    <MobileContainer
      history={history}
      data={data}
      userAvatar={userAvatar}
      modalActive={modalActive}
      modalStateOn={modalStateOn}
      modalStateOff={modalStateOff}
      isLoggedIn={isLoggedIn}
    >
      {children}
    </MobileContainer>
  </React.Fragment>
);

function mapStateToProps(state) {
  const { ui, users } = state;
  const { isLoggedIn, userAvatar } = users;
  const { modalActive } = ui;

  return { isLoggedIn, userAvatar, modalActive };
}

const mapDispatchToProps = dispatch =>
  bindActionCreators({ modalStateOn, modalStateOff, loadAvatar }, dispatch);

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(LinkNavWithLayout);

此片段包含使用类编写的组件。这就是它的样子

但是在将其切换为功能性时,有两件事停止工作:

移动侧抽屉无法打开和关闭。但是,如果使用传递硬编码的值true,当您进入移动视图时,它确实会打开。

第二个是,当路由器更改 URL 时,相应的组件不会呈现。例如/profile应该带一个到个人资料页面

为了解决汉堡菜单,我尝试使用useCallback一些我认为是处理正确渲染的好策略。但无济于事。基本上是一个总是返回正确值的函数。Open menu === trueClosed menu === false

我什至设置了一个useEffect钩子来触发isToggled价值的日志,只是为了确保事情是洁净的。

  var useToggle = initialState => {
    const [isToggled, setIsToggled] = React.useState(initialState);
    const toggle = useCallback(() => setIsToggled(state => !state), [setIsToggled]);

    return [isToggled, toggle];
  };

  var [fixed, setFixed] = useState(null);
  var [isToggled, toggle] = useToggle(false);
  var [Content, setContent] = useState(null);

  var [isMobile, setIsMobile] = useState(false);
  var [isDesktop, setIsDesktop] = useState(false);

  var handleSidebarHide = () => false;
 

  var hideFixedMenu = () => setFixed(false);
  var showFixedMenu = () => setFixed(true);

  useEffect(() => {
    console.log('isToggled', isToggled);
  }, [isToggled]);

这是完整的组件:

import React, { useCallback, useState, useEffect, useContext } from 'react';
import { Link, NavLink } from 'react-router-dom';
import Modal from '../components/Modal/MyModal.jsx';
import {
  Container,
  Menu,
  Responsive,
  Segment,
  Visibility,
  Sidebar,
  Icon,
  Button
} from 'semantic-ui-react';

import { connect } from 'react-redux';
import { modalStateOn, modalStateOff } from '../store/reducers/ui/index';

import UserContext from '../components/UserContext/UserContext.jsx';

const getWidth = () => {
  const isSSR = typeof window === 'undefined';
  return isSSR ? Responsive.onlyTablet.minWidth : window.innerWidth;
};

function logOutMenuItemHelper(
  isMobile,
  isLoggedIn,
  history,
  modalActive,
  nav,
  NavLink,
  modalStateOn,
  modalStateOff,
  handleSidebarHide
) {
  function mobilelogOutMenuItemHelper(
    history,
    modalActive,
    nav,
    NavLink,
    modalStateOn,
    handleSidebarHide
  ) {
    if (nav.name === 'Log in') {
      return (
        <React.Fragment key={'modalForMobile'}>
          {modalActive && (
            <Modal
              isAlertModal={false}
              history={history}
              affirmativeUsed="Yes"
              message=" Are you sure you want to log out of your account?"
              modalActive={modalActive}
            />
          )}
          <Menu.Item
            key={'modalForMobile'}
            name="Log out"
            onClick={event => {
              modalStateOn();
              handleSidebarHide();
            }}
          >
            Log Out
          </Menu.Item>
        </React.Fragment>
      );
    } else {
      return (
        <Menu.Item
          exact
          key={nav.name}
          as={NavLink}
          to={nav.path}
          name={nav.name}
          onClick={() => {
            handleSidebarHide();
          }}
        />
      );
    }
  }

  function desktoplogOutMenuItemHelper(
    history,
    modalActive,
    nav,
    NavLink,
    modalStateOn,
    modalStateOff
  ) {
    if (nav.name === 'Log in') {
      return (
        <React.Fragment key={'modalForDesktop'}>
          {modalActive && (
            <Modal
              isAlertModal={false}
              history={history}
              affirmativeUsed="Yes"
              message="Are you sure you want to log out of your account?"
              modalActive={modalActive}
            />
          )}
          <Menu.Item
            key={'modalForDesktop'}
            name="Log out"
            onClick={event => {
              modalStateOn();
              window.localStorage.clear();
            }}
          >
            Log Out
          </Menu.Item>
        </React.Fragment>
      );
    } else {
      return (
        <Menu.Item exact key={nav.name} as={NavLink} to={nav.path} name={nav.name} />
      );
    }
  }

  if (isMobile && isLoggedIn) {
    return mobilelogOutMenuItemHelper(
      history,
      modalActive,
      nav,
      NavLink,
      modalStateOn,
      handleSidebarHide
    );
  }
  return desktoplogOutMenuItemHelper(
    history,
    modalActive,
    nav,
    NavLink,
    modalStateOn,
    modalStateOff
  );
}

function LayoutContainer({
  children,
  history,
  data,
  isLoggedIn,
  modalActive,
  modalStateOn,
  modalStateOff,
  userData
}) {
  var useToggle = initialState => {
    const [isToggled, setIsToggled] = React.useState(initialState);
    const toggle = useCallback(() => setIsToggled(state => !state), [setIsToggled]);

    return [isToggled, toggle];
  };

  var [fixed, setFixed] = useState(null);
  var [isToggled, toggle] = useToggle(false);
  var [Content, setContent] = useState(null);

  var [isMobile, setIsMobile] = useState(false);
  var [isDesktop, setIsDesktop] = useState(false);

  var handleSidebarHide = () => false;
  // var handleToggle = () => setSideBarOpened(true);

  var hideFixedMenu = () => setFixed(false);
  var showFixedMenu = () => setFixed(true);

  useEffect(() => {
    console.log('isToggled', isToggled);
  }, [isToggled]);

  useEffect(() => {
    console.log('window.innerWidth in first render', window.innerWidth);
    if (window.innerWidth < 768) {
      setIsMobile(true);
      setIsDesktop(false);
    } else {
      setIsDesktop(true);
      setIsMobile(false);
    }
    console.log('isMobile, isDesktop 175', isMobile, isDesktop);
  }, []);

  useEffect(() => {
    window.addEventListener(
      'resize',
      function(e) {
        if (e.target.innerWidth < 768) {
          setIsMobile(isMobile => true);
          setIsDesktop(isDesktop => false);
        }

        if (e.target.innerWidth > 767) {
          setIsDesktop(isDesktop => true);
          setIsMobile(isMobile => false);
        }
      },
      false
    );
    console.log('Line 194', isMobile, isDesktop);
  }, [isMobile, isDesktop]);

  useEffect(() => {
    if (window.innerWidth < 768) {
      setContent(Content => (
        <Responsive
          as={Sidebar.Pushable}
          getWidth={getWidth}
          maxWidth={Responsive.onlyMobile.maxWidth}
        >
          <Sidebar
            as={Menu}
            animation="push"
            inverted
            onHide={handleSidebarHide}
            vertical
            visible={isToggled}
          >
            {isLoggedIn
              ? data
                  .filter(function(nav) {
                    return nav.name !== 'Register';
                  })
                  .map(nav => {
                    return logOutMenuItemHelper(
                      true,
                      isLoggedIn,
                      history,
                      modalActive,
                      nav,
                      NavLink,
                      modalStateOn,
                      modalStateOff,
                      handleSidebarHide
                    );
                  })
              : data
                  .filter(function(nav) {
                    return nav.name != 'Profile' && nav.name != 'Dashboard';
                  })
                  .map(nav => {
                    return (
                      <Menu.Item
                        exact
                        key={nav.name}
                        as={NavLink}
                        to={nav.path}
                        name={nav.name}
                        onClick={handleSidebarHide}
                      />
                    );
                  })}
          </Sidebar>

          <Sidebar.Pusher dimmed={isToggled}>
            <Segment
              inverted
              textAlign="center"
              style={{ minHeight: 'auto', padding: '1em 0em' }}
              vertical
            >
              <Container>
                <Menu inverted pointing secondary size="large">
                  <Menu.Item onClick={() => toggle()}>
                    <Icon name="sidebar" />
                  </Menu.Item>
                  <Menu.Item position="right">
                    <Button inverted>
                      {isLoggedIn ? (
                        <Link to="#" onClick={modalStateOn}>
                          Log out
                        </Link>
                      ) : (
                        <Link to="/login">Log in</Link>
                      )}
                    </Button>
                    {!isLoggedIn ? (
                      <Button inverted style={{ marginLeft: '0.5em' }}>
                        <Link to="/register">
                          <span>Register!</span>
                        </Link>
                      </Button>
                    ) : null}
                  </Menu.Item>
                </Menu>
              </Container>
            </Segment>

            {React.cloneElement(children, { userData })}
          </Sidebar.Pusher>
        </Responsive>
      ));
    } else {
      setContent(Content => (
        <Responsive getWidth={getWidth} minWidth={Responsive.onlyTablet.minWidth}>
          <Visibility
            once={false}
            onBottomPassed={showFixedMenu}
            onBottomPassedReverse={hideFixedMenu}
          >
            <Segment
              inverted
              textAlign="center"
              style={{ minHeight: 'auto', padding: '0' }}
              vertical
            >
              <Menu
                fixed={fixed ? 'top' : null}
                inverted={!fixed}
                pointing={!fixed}
                secondary={!fixed}
                size="large"
              >
                {/* {console.log("isLoggedIn in desktop homecomponent ", isLoggedIn)} */}
                {isLoggedIn
                  ? data
                      .filter(function(nav) {
                        return nav.name !== 'Register';
                      })
                      .map(nav => {
                        return logOutMenuItemHelper(
                          false,
                          isLoggedIn,
                          history,
                          modalActive,
                          nav,
                          NavLink,
                          modalStateOn,
                          modalStateOff
                        );
                      })
                  : data
                      .filter(function(nav) {
                        return nav.name != 'Profile' && nav.name != 'Dashboard';
                      })
                      .map(nav => {
                        return (
                          <Menu.Item
                            exact
                            key={nav.path}
                            as={NavLink}
                            to={nav.path}
                            name={nav.name}
                          />
                        );
                      })}
              </Menu>
            </Segment>
          </Visibility>
          {React.cloneElement(children, { userData })}
        </Responsive>
      ));
    }
  }, [isMobile, isDesktop]);

  return isMobile ? Content : Content;
}

const LinkNavWithLayout = ({
  children,
  history,
  data,
  modalActive,
  modalStateOn,
  modalStateOff,
  isLoggedIn
}) => {
  var userData = useContext(UserContext);
  return (
    <React.Fragment>
      <LayoutContainer
        history={history}
        data={data}
        modalActive={modalActive}
        modalStateOn={modalStateOn}
        modalStateOff={modalStateOff}
        isLoggedIn={isLoggedIn}
        userData={userData}
      >
        {children}
      </LayoutContainer>
    </React.Fragment>
  );
};

function mapStateToProps(state) {
  const { ui, users } = state;
  const { isLoggedIn } = users;
  const { modalActive } = ui;

  return { isLoggedIn, modalActive };
}

const mapDispatchToProps = dispatch => ({
  modalStateOn: () => dispatch(modalStateOn()),
  modalStateOff: () => dispatch(modalStateOff())
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(LinkNavWithLayout);

提前致谢!

标签: javascriptreactjsreact-hooksuse-effectuse-state

解决方案


看起来我忘记了这个布局的一个重要方面,它改变了一个功能版本!

除了处理由于浏览器宽度变化而导致的组件的不同布局之外,我忘记在useEffect功能挂钩中添加其他重要的依赖项(汉堡侧面板、模态功能等)。特别是fixed, children, isToggled, modalActive

当我继续引用prop/state它所依赖的值的类版本时,自然地,功能组件在外观和感觉上都比原来的(类版本)有所改进。

这是仅使用钩子的新更新版本 \o/

import React, { useCallback, useState, useEffect, useContext } from 'react';
import { Link, NavLink } from 'react-router-dom';
import Modal from '../components/Modal/MyModal.jsx';
import {
  Container,
  Menu,
  Responsive,
  Segment,
  Visibility,
  Sidebar,
  Icon,
  Button
} from 'semantic-ui-react';

import { connect } from 'react-redux';
import { modalStateOn, modalStateOff } from '../store/reducers/ui/index';

import UserContext from '../components/UserContext/UserContext.jsx';

const getWidth = () => {
  const isSSR = typeof window === 'undefined';
  return isSSR ? Responsive.onlyTablet.minWidth : window.innerWidth;
};

function logOutMenuItemHelper(
  isMobile,
  isLoggedIn,
  history,
  modalActive,
  nav,
  NavLink,
  modalStateOn,
  modalStateOff,
  handleSidebarHide
) {
  function mobilelogOutMenuItemHelper(
    history,
    modalActive,
    nav,
    NavLink,
    modalStateOn,
    handleSidebarHide
  ) {
    if (nav.name === 'Log in') {
      return (
        <React.Fragment key={'modalForMobile'}>
          {modalActive && (
            <Modal
              isAlertModal={false}
              history={history}
              affirmativeUsed="Yes"
              message=" Are you sure you want to log out of your account?"
              modalActive={modalActive}
            />
          )}
          <Menu.Item
            key={'modalForMobile'}
            name="Log out"
            onClick={event => {
              modalStateOn();
              handleSidebarHide();
            }}
          >
            Log Out
          </Menu.Item>
        </React.Fragment>
      );
    } else {
      console.log('nav.path ', nav.path);
      return (
        <Menu.Item
          exact
          key={nav.name}
          as={NavLink}
          to={nav.path}
          name={nav.name}
          onClick={handleSidebarHide}
        />
      );
    }
  }

  function desktoplogOutMenuItemHelper(
    history,
    modalActive,
    nav,
    NavLink,
    modalStateOn,
    modalStateOff
  ) {
    if (nav.name === 'Log in') {
      return (
        <React.Fragment key={'modalForDesktop'}>
          {modalActive && (
            <Modal
              isAlertModal={false}
              history={history}
              affirmativeUsed="Yes"
              message="Are you sure you want to log out of your account?"
              modalActive={modalActive}
            />
          )}
          <Menu.Item
            key={'modalForDesktop'}
            name="Log out"
            onClick={event => {
              modalStateOn();
            }}
          >
            Log Out
          </Menu.Item>
        </React.Fragment>
      );
    } else {
      return (
        <Menu.Item exact key={nav.name} as={NavLink} to={nav.path} name={nav.name} />
      );
    }
  }

  if (isMobile && isLoggedIn) {
    return mobilelogOutMenuItemHelper(
      history,
      modalActive,
      nav,
      NavLink,
      modalStateOn,
      handleSidebarHide
    );
  }
  return desktoplogOutMenuItemHelper(
    history,
    modalActive,
    nav,
    NavLink,
    modalStateOn,
    modalStateOff
  );
}

function LayoutContainer({
  children,
  history,
  data,
  isLoggedIn,
  modalActive,
  modalStateOn,
  modalStateOff,
  userData
}) {
  var useToggle = initialState => {
    const [isToggled, setIsToggled] = React.useState(initialState);
    const toggle = useCallback(() => setIsToggled(state => !state), [setIsToggled]);

    return [isToggled, toggle];
  };

  var [data, setData] = useState(data);

  var [fixed, setFixed] = useState(null);
  var [isToggled, toggle] = useToggle(false);
  var [Content, setContent] = useState(null);

  var [isMobile, setIsMobile] = useState(false);
  var [isDesktop, setIsDesktop] = useState(false);

  function handleSidebarHide() {
    if (isToggled == true) return toggle();
  }
  // var handleToggle = () => setSideBarOpened(true);

  var hideFixedMenu = () => setFixed(false);
  var showFixedMenu = () => setFixed(true);

  useEffect(() => {
    console.log('isToggled ', isToggled);
  }, [isToggled]);

  useEffect(() => {
    console.log('window.innerWidth in first render', window.innerWidth);
    if (window.innerWidth < 768) {
      setIsMobile(true);
      setIsDesktop(false);
    } else {
      setIsDesktop(true);
      setIsMobile(false);
    }
    console.log('isMobile, isDesktop 192', isMobile, isDesktop);
  }, []);

  useEffect(() => {
    window.addEventListener(
      'resize',
      function(e) {
        if (e.target.innerWidth < 768) {
          setIsMobile(isMobile => true);
          setIsDesktop(isDesktop => false);
        }

        if (e.target.innerWidth > 767) {
          setIsDesktop(isDesktop => true);
          setIsMobile(isMobile => false);
        }
      },
      false
    );
    console.log('isMobile, isDesktop Line 194', isMobile, isDesktop);
  }, [isMobile, isDesktop]);

  useEffect(() => {
    if (window.innerWidth < 768) {
      setContent(Content => {
        return (
          <Responsive
            as={Sidebar.Pushable}
            getWidth={getWidth}
            maxWidth={Responsive.onlyMobile.maxWidth}
          >
            <Sidebar
              as={Menu}
              animation="push"
              inverted
              onHide={() => handleSidebarHide()}
              vertical
              visible={isToggled}
            >
              {isLoggedIn
                ? data
                    .filter(function(nav) {
                      return nav.name !== 'Register';
                    })
                    .map(nav => {
                      return logOutMenuItemHelper(
                        true,
                        isLoggedIn,
                        history,
                        modalActive,
                        nav,
                        NavLink,
                        modalStateOn,
                        modalStateOff,
                        handleSidebarHide
                      );
                    })
                : data
                    .filter(function(nav) {
                      return nav.name != 'Profile' && nav.name != 'Dashboard';
                    })
                    .map(nav => {
                      return (
                        <Menu.Item
                          exact
                          key={nav.name}
                          as={NavLink}
                          to={nav.path}
                          name={nav.name}
                          onClick={handleSidebarHide}
                        />
                      );
                    })}
            </Sidebar>

            <Sidebar.Pusher dimmed={isToggled}>
              <Segment
                inverted
                textAlign="center"
                style={{ minHeight: 'auto', padding: '1em 0em' }}
                vertical
              >
                <Container>
                  <Menu inverted pointing secondary size="large">
                    <Menu.Item onClick={toggle}>
                      <Icon name="sidebar" />
                    </Menu.Item>
                    <Menu.Item position="right">
                      <Button inverted>
                        {modalActive && (
                          <Modal
                            isAlertModal={false}
                            history={history}
                            affirmativeUsed="Yes"
                            message="Are you sure you want to log out of your account?"
                            modalActive={modalActive}
                          />
                        )}
                        {isLoggedIn ? (
                          <Link to="/" onClick={modalStateOn}>
                            Log out
                          </Link>
                        ) : (
                          <Link to="/login">Log in</Link>
                        )}
                      </Button>
                      {!isLoggedIn ? (
                        <Button inverted style={{ marginLeft: '0.5em' }}>
                          <Link to="/register">
                            <span>Register!</span>
                          </Link>
                        </Button>
                      ) : null}
                    </Menu.Item>
                  </Menu>
                </Container>
              </Segment>

              {React.cloneElement(children, { userData })}
            </Sidebar.Pusher>
          </Responsive>
        );
      });
    } else {
      setContent(Content => (
        <Responsive getWidth={getWidth} minWidth={Responsive.onlyTablet.minWidth}>
          <Visibility
            once={false}
            onBottomPassed={showFixedMenu}
            onBottomPassedReverse={hideFixedMenu}
          >
            <Segment
              inverted
              textAlign="center"
              style={{ minHeight: 'auto', padding: '0' }}
              vertical
            >
              <Menu
                fixed={fixed ? 'top' : null}
                inverted={!fixed}
                pointing={!fixed}
                secondary={!fixed}
                size="large"
              >
                {/* {console.log("isLoggedIn in desktop homecomponent ", isLoggedIn)} */}
                {isLoggedIn
                  ? data
                      .filter(function(nav) {
                        return nav.name !== 'Register';
                      })
                      .map(nav => {
                        return logOutMenuItemHelper(
                          false,
                          isLoggedIn,
                          history,
                          modalActive,
                          nav,
                          NavLink,
                          modalStateOn,
                          modalStateOff
                        );
                      })
                  : data
                      .filter(function(nav) {
                        return nav.name != 'Profile' && nav.name != 'Dashboard';
                      })
                      .map(nav => {
                        return (
                          <Menu.Item
                            key={nav.path}
                            as={NavLink}
                            to={nav.path}
                            name={nav.name}
                          />
                        );
                      })}
              </Menu>
            </Segment>
          </Visibility>
          {React.cloneElement(children, { userData })}
        </Responsive>
      ));
    }
  }, [fixed, children, isMobile, isDesktop, isToggled, modalActive]);

  return isMobile ? Content : Content;
}

const LinkNavWithLayout = ({
  children,
  history,
  data,
  modalActive,
  modalStateOn,
  modalStateOff,
  isLoggedIn
}) => {
  var userData = useContext(UserContext);
  return (
    <React.Fragment>
      <LayoutContainer
        history={history}
        data={data}
        modalActive={modalActive}
        modalStateOn={modalStateOn}
        modalStateOff={modalStateOff}
        isLoggedIn={isLoggedIn}
        userData={userData}
      >
        {children}
      </LayoutContainer>
    </React.Fragment>
  );
};

function mapStateToProps(state) {
  const { ui, users } = state;
  const { isLoggedIn } = users;
  const { modalActive } = ui;

  return { isLoggedIn, modalActive };
}

const mapDispatchToProps = dispatch => ({
  modalStateOn: () => dispatch(modalStateOn()),
  modalStateOff: () => dispatch(modalStateOff())
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(LinkNavWithLayout);

推荐阅读