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♀️
我一直在关注这个 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♀️