Header 当我使用 useNavigate Hook 时组件停止显示

Header Component Stopped Showing When I Used useNavigate Hook

我一直在关注这个 video series on creating a special type of dropdown hamburger menu. When I got to this part 视频我不得不做一些改变,因为我使用的是 React router dom v6 并且了解到 withRouter已弃用。

目前,一旦我点击 link 进入新页面,菜单就会消失。但是在添加 useNavigate 钩子后,我的 header 完全消失了。我还不是 100% 熟悉反应中的一些钩子,并且发现自己坚持让我的 header 再次出现并让菜单工作。我已经将我正在使用的代码放在下面,并且真的可以使用一些指导来了解如何在不切换到 v5 和继续观看视频教程的情况下让它工作。

App.js

import "./App.scss";
import Header from "./components/Header";
import MenuWrapper from "./components/MenuWrapper";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

function App() {
  return (
    <Router>
      <div className="App">
        <MenuWrapper>
          <Header />
        </MenuWrapper>
        <div className="container">
          <div className="wrapper">
            <div className="home">
              <Routes>
                <Route exact path="/" element={<Home />} />
                <Route
                  exact
                  path="/opportunities"
                  element={<Opportunities />}
                />
                <Route exact path="/solutions" element={<Solutions />} />
                <Route exact path="/contact-us" element={<Contact />} />
              </Routes>
            </div>
          </div>
        </div>
      </div>
    </Router>
  );
}

function Opportunities() {
  return <p>Discover our numerous opportunities</p>;
}

function Solutions() {
  return <p>Solutions that help you.</p>;
}

function Contact() {
  return <p>Feel free to reach us.</p>;
}

function Home() {
  return (
    <div className="container">
      <div className="wrapper">
        <h5>
          The <b>HAMBRG</b>, is a creative, engineer driven, global agency
          working on advancing the software, advertising and design communities
          to new heights.
        </h5>
      </div>
    </div>
  );
}
export default App;

MenuWrapper.jsx


const withRouter = (Component) => {
  const MenuWrapper = (props) => {
    const history = useNavigate();

    return <Component history={history} {...props} />;
  };

  return MenuWrapper;
};
export default withRouter;

Header.jsx

import { Link } from "react-router-dom";
import Hamburger from "./Hamburger";

const Header = () => {
  //State for menu button
  const [state, setState] = useState({
    initial: false,
    clicked: null,
    menuName: "Menu",
  });

  //State for disabled button
  const [disabled, setDisabled] = useState(false);

  //Use effect for page changes
  useEffect((history) => {
    history.listen(() => {
      setState({ clicked: false, menuName: "Menu" });
    });
  });

  const handleMenu = () => {
    disableMenu();
    if (state.initial === false) {
      setState({
        initial: null,
        clicked: true,
        menuName: "Close",
      });
    } else if (state.clicked === true) {
      setState({
        clicked: !state.clicked,
        menuName: "Menu",
      });
    } else if (state.clicked === false) {
      setState({
        clicked: !state.clicked,
        menuName: "Close",
      });
    }
  };

  //Determine if our menu should be disabled
  const disableMenu = () => {
    setDisabled(!disabled);
    setTimeout(() => {
      setDisabled(false);
    }, 1200);
  };

  return (
    <header>
      <div className="container">
        <div className="wrapper">
          <div className="inner-header">
            <div className="logo">
              <Link to="/">HAMRG.</Link>
            </div>
            <div className="menu">
              <button disabled={disabled} onClick={handleMenu}>
                Menu
              </button>
            </div>
          </div>
        </div>
      </div>
      <Hamburger state={state} />
    </header>
  );
};

export default Header;

Hamburger.jsx

import { Link } from "react-router-dom";

const Hamburger = ({ state }) => {
  let menu = useRef(null);

  useEffect(() => {
    if (state.clicked === false) {
      // close the menu
      menu.style.display = "none";
    } else if (
      state.clicked === true ||
      (state.clicked === true && state.initial === null)
    ) {
      // open the  menu
      menu.style.display = "block";
    }
  });

  return (
    <div ref={(el) => (menu = el)} className="hamburger-menu">
      <div className="menu-secondary-background-color"></div>
      <div className="menu-layer">
        <div className="menu-city-background"></div>
        <div className="container">
          <div className="wrapper">
            <div className="menu-links">
              <nav>
                <ul>
                  <li>
                    <Link to="/opportunities">Opportunities</Link>
                  </li>
                  <li>
                    <Link to="/solutions">Solutions</Link>
                  </li>
                  <li>
                    <Link to="/contact-us">Contact Us</Link>
                  </li>
                </ul>
              </nav>
              <div className="info">
                <h3>Our Promise</h3>
                <p>
                  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
                  do eiusmod tempor incididunt ut labore et dolore magna aliqua.
                  Ut enim ad minim veniam, quis nostrud exercitation ullamco
                  laboris nisi ut aliquip ex ea commodo consequat. Duis aute
                  irure dolor in reprehenderit in voluptate velit esse cillum
                  dolore eu fugiat nulla pariatur. Excepteur sint occaecat
                  cupidatat non proident, sunt in culpa qui officia deserunt
                  mollit anim id est laborum.
                </p>
              </div>
              <div className="locations">
                Location:
                <span>Dallas</span>
                <span>Austin</span>
                <span>New York</span>
                <span>San Francisco</span>
                <span>Beijing</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Hamburger;

这里有几件事 - 你根本不需要 withRouter 包装器 - 它真正做的就是将 navigate 属性 传递给包装元素(但你'实际上并没有使用它)。如果你需要一个 navigate 在包装元素中,你可以只使用钩子 -

const Header = () => {
    // If you need 'navigate', just use the hook
    const navigate = useNavigate();
};

现在,查看 final code from the tutorial, it looks like the history was only being used to listen to page changes; you could do the same thing with useLocation -

const Header = () => {
  // ----- 8< -----
  const location = useLocation();

  useEffect(() => {
    setState({ clicked: false, menuName: "Menu" });
  }, [location]);
};

你在 Hamburger.js 的效果中也有一个错误(可能?):

useEffect(() => {
    if (state.clicked === false) {
      // close the menu
      menu.style.display = "none";
    } else if (
      state.clicked === true ||
      (state.clicked === true && state.initial === null)
    ) {
      // open the menu
      menu.style.display = "block";
    }
});

这里的else if不正确。如果state.clicked === true那么if就会短路;如果 state.click === false 那么左侧和右侧都不会计算为 true;所以换句话说,你只是在检查:

if (state.clicked === true) {
}

可能是你想要的,也可能是bug‍♀️