我在使用useContext管理导航栏的状态时遇到问题。Atm我的应用程序在菜单切换后立即呈现菜单项。我希望此事件仅在单击一次时发生,并且按钮不记录console.log消息,它仅在我直接单击链接项ex:home时起作用。所以我有两个问题。如何管理导航栏状态以显示如何隐藏菜单项,而不必为其创建新组件?如何修复在菜单按钮本身或/和菜单项上触发的单击事件?下面您将为App.js、Layout.js、ThemeContext.js、useTheme.js、usetokle.js、ToggleContext.js和使用切换上下文的导航栏编写代码片段。
我真的很想在这里得到一些帮助,伙计们,我是低年级学生,真的有点被困在这里了。提前感谢大家。
狮子座
一个pp.js
//import { data } from '../../SkillData';
import Header from './Header';
import Navbar from './Navbar';
import Skills from './Skills';
import Layout from './Layout';
function App () {
return (
<Layout startingTheme="light" startingToggle={"show"}>
<div>
<Navbar />
<Header />
<Skills />
</div>
</Layout>
);
}
export default App;
我ayout.js
import React, { useContext } from "react";
import { ThemeContext, ThemeProvider } from "../contexts/ThemeContext";
import { ToggleContext, ToggleProvider } from "../contexts/ToggleContext";
function Layout ({startingTheme, startingToggle, children}) {
return (
<>
<ThemeProvider startingTheme={startingTheme} >
<ToggleProvider startingToggle={startingToggle}>
<LayoutNoToggleProvider>
</LayoutNoToggleProvider>
</ToggleProvider>
<LayoutNoThemeProvider >{children}</LayoutNoThemeProvider>
</ThemeProvider>
</>
);
}
function LayoutNoToggleProvider ({children}) {
const toggle = useContext(ToggleContext);
return (
<div className={
toggle === false ? "navbar navbar-collapsed" : "navbar navbar-collapse show"
}>
{children}
</div>
)
}
function LayoutNoThemeProvider ({ children }) {
const {theme} = useContext(ThemeContext);
return (
<div className={
theme === "light" ?
"container-fluid bg-white" :
"container-fluid bg-dark"
}>
{children}
</div>
);
}
export default Layout;
主题文本
import React, { createContext} from "react";
import useTheme from "../hooks/useTheme";
export const ThemeContext = createContext();
function ThemeProvider ({children, startingTheme}) {
const { theme, setTheme } = useTheme(startingTheme);
return (
<ThemeContext.Provider value={
{theme, setTheme}
}>
{children}
</ThemeContext.Provider>
);
}
export { ThemeProvider };
useTheme.js
import { useState } from "react";
function useTheme (startingTheme ="light") {
const [theme, setTheme] = useState(startingTheme);
function validateTheme (themeValue) {
if (themeValue === "dark") {
setTheme("dark");
} else {
setTheme("light");
}
}
return {
theme,
setTheme: validateTheme,
}
}
export default useTheme;
ToggleContext.js
import React, { createContext } from "react";
import useToggle from "../hooks/useToggle";
export const ToggleContext = createContext();
function ToggleProvider({ children, startingToggle }) {
const { toggle, setToggle } = useToggle(startingToggle);
return (
<ToggleContext.Provider value={{ toggle, setToggle }}>
{children}
</ToggleContext.Provider>
);
}
export { ToggleProvider };
usetokle.js
import { useState } from "react";
function useToggle (startingToggle = false) {
const [toggle, setToggle] = useState(startingToggle);
function validateShowSidebar (showSidebarValue) {
if (showSidebarValue === "show") {
setToggle("show");
} else {
setToggle("");
}
}
return {
toggle,
setToggle: validateShowSidebar,
}
}
export default useToggle;
Navbar.js
import Image from "next/image";
import styles from "../../styles/Home.module.scss"
import Logo from "../../public/Knowledge Memo.svg"
import { useContext } from "react";
import { ThemeContext } from "../contexts/ThemeContext";
import { ToggleContext } from "../contexts/ToggleContext";
import Link from 'next/link';
import { useState } from "react";
const navbarData = [
{ id: "1",
title: "home",
ref: "#home"
},
{ id:"2",
title: "Skills",
ref: "#skills"
},
{ id:"3",
title: "The List",
ref: "#theList"
},
{ id: "4",
title: "Team",
ref: "#team"
},
{ id: "5",
title: "Contact",
ref: "#contact"
},
];
function Navbar() {
const theme = useContext(ThemeContext);
const toggle = useContext(ToggleContext);
return (
<>
<nav className={
theme === "light" ?
"navbar navbar-expand-lg navbar-dark fixed-top":
"navbar navbar-expand-lg navbar-dark bg-dark fixed-top id= mainNav"}>
<div className="container d-flex flex justify-content-between">
<a className="navbar-brand h-50" href="#page-top">
<div className="navbar-brand">
<Image
src={Logo}
alt="..."
fill="#fff"
objectFit="contain"
className="h-50"
/>
</div>
</a>
<button
onClick={ () => toggle === !toggle, console.log("clicked")}
className="navbar-toggler collapsed"
type="button"
data-bs-toggle="collapsed"
data-bs-target="#navbarResponsive"
aria-controls="navbarResponsive"
aria-expanded="false"
aria-label="Toggle navigation"
>
Menu
<i className="fa fa-bars ms-1 navbar-toggler" aria-hidden="true"></i>
</button>
{toggle ?
<div className="collapsed navbar-collapse mt-2 id=navbarResponsive">
<ul className="navbar-nav text-uppercase ms-auto py-4 py-lg-0">
{navbarData.map((link,idx) => {
return (
<li key={link.id}>
<Link href={`/${link.ref}`} className="nav-item" data-index={idx} passHref>
<a className="nav-link">
{link.title}
</a>
</Link>
</li>
);
})}
</ul>
</div>
: <div className="collapse navbar-collapse show mt-2 id=navbarResponsive">
<ul className="navbar-nav show text-uppercase ms-auto py-4 py-lg-0">
{navbarData.map((link,idx) => {
return (
<li key={link.id}>
<Link href={`/${link.ref}`} className="nav-item" data-index={idx} passHref>
<a className="nav-link">
{link.title}
</a>
</Link>
</li>
);
})}
</ul>
</div>}
</div>
</nav>
</>
);
}
export default Navbar;
您可以使用reducer来尝试此实现,以便使用localstorage处理状态更改。这不是一个确切的暗示,但你可以看到流程
在AppContext.jsx中
AppContext保存应用程序的全局状态,因此可以更轻松地使用单个上下文提供程序,并将Acton分派到特定的简化程序以处理状态更改,而无需提供多个提供程序。combinedReducer
将reducer方法处理为给定的状态组件
import { useReducer, createContext, useEffect } from "react";
import userReducer from "./reducers/userReducer";
import themeReducer from "./reducers/themeReducer";
export const APP_NAME = "test_app";
//Check the localstorage or set a default state
const initialState = JSON.parse(localStorage.getItem(APP_NAME))
? JSON.parse(localStorage.getItem(APP_NAME))
: {
user: {
username: "",
email: "",
isAdmin: false,
},
theme: { dark: false },
};
//Create your global context
const AppContext = createContext(initialState);
//Create combined reducers
const combinedReducers = ({ user, theme }, action) => ({
user: userReducer(user, action),
theme: themeReducer(theme, action),
});
const AppState = ({ children }) => {
//Making it to provider state
const [state, dispatch] = useReducer(combinedReducers, initialState);
useEffect(() => {
localStorage.setItem(APP_NAME, JSON.stringify(state));
}, [state]);
return (
<AppContext.Provider value={{ state, dispatch }}>
{children}
</AppContext.Provider>
);
};
export default AppState;
export { AppContext, AppState };
上述实现的工作原理类似于redux
,但您可以将给定的状态分解为特定的缩减器来处理状态更改
在这一点上,我使用localstore来保持持久状态,因为在页面上使用上下文API
重新加载状态。使用use效应
钩子从反应
,并在依赖数组中添加状态,以确保您的状态是同步的
在UserReducer.jsx中
const userReducer = (state, action) => {
const { type, payload } = action;
switch (type) {
case "LOGIN":
return { ...state, ...payload };
case "LOGOUT":
return {};
default:
return state;
}
};
export default userReducer;
在
ThemeReducer.jsx中
const themeReducer = (state, action) => {
const { type, payload } = action;
switch (type) {
case "DARK":
return { ...payload };
default:
return state;
}
};
export default themeReducer;
在
index.jsx中使用单个提供者包装整个应用程序
import reactDom from "react-dom"
import React from "react"
import App from "./App"
import "./index.css"
import AppState from "./state/AppState"
reactDom.render(
<React.StrictMode>
<AppState >
<App />
</AppState>
</React.StrictMode>,
document.getElementById("root")
)
从
App.jsx
import { useContext } from "react";
import { AppContext } from "./state/AppState";
const App = () => {
const { state, dispatch } = useContext(AppContext);
const handleLogin = () => {
dispatch({
type: "LOGIN",
payload: {
username: "Mike",
email: "mike@gmail.com",
isAdmin: false,
},
});
};
const handleLogout = () => {
dispatch({
type: "LOGOUT",
payload: {},
});
};
return (
<div className="main-container">
<div className="container">
<p>Username: {state.user.username ? state.user.username : "Unknown"}</p>
<p>Email: {state.user.email ? state.user.email : "Unknown"}</p>
</div>
<button onClick={handleLogin}>Login</button>
<button onClick={handleLogout} style={{ background: "red" }}>
Login
</button>
</div>
);
};
export default App;
如果你想看Github的结构,这是我的代码链接
首先,我想说我从来没有使用过Next.js或context api,所以请耐心听我说。 我目前正在Next.js中开发一个web应用程序,其中有多个页面,每个页面都包含一个表单。我希望有某种全局状态,以便能够设置和更新每个表单的数据。所有表单数据一起 例如:第1页=名称,第2页=说明,... 从我在网上读到的内容来看,我认为使用上下文api就足够了,但我遇到了困难。当我在第一个表单上填写名字时,它
我正在尝试将openapi/swagger文件导入api网关,但无法按预期获得安全设置。我希望所有路径都需要一个api密钥。 导入后在控制台中设置它所需的api密钥是可行的,但这种解决方案是不可取的,同样可行的是在每个路径中单独设置安全字段,但我正在寻找全局解决方案。 当我尝试导入文件时,我会收到以下警告: 看起来,我要么需要一个lambda作为api密钥的自定义授权器(我不熟悉授权器,但如果我在
问题内容: 我正在尝试在我的应用程序上使用React 16.3中的新上下文API进行一些测试,但我不明白为什么我的重定向永远无法工作。 我不想让我的ContextB可用于所有路由,仅2和3。我该怎么做? 问题答案: 看起来应该只具有和`<Redirect `组件作为直接子代。(来源) 我想这就是为什么你的,你使用不工作的孩子。 最简单但重复的解决方案可能是让您成为每个想要的孩子的孩子: 注意:这些
我试图在我的应用程序上用React 16.3的新上下文API做一些测试,但是我不明白为什么我的重定向从来没有工作过。 我不想让我的ContextB适用于所有路线,只适用于2号和3号路线。我该怎么做?
问题内容: 看起来像这样自然是很自然的: 但是Python并未为套接字实现上下文管理器。我可以轻松地将其用作上下文管理器吗? 问题答案: 该模块相当底层,使您几乎可以直接访问C库功能。 您始终可以使用装饰器来构建自己的装饰器: 或用于达到相同效果: 但是装饰器使您有机会首先使用套接字执行其他操作。 Python 3.x确实可以创建上下文管理器,但是直到2016年Python 3.5周期才进行 更新
问题内容: 先前曾问过一个有关如何覆盖环境指令中定义的变量的问题,看来这是不可能的。 我想在一个阶段中设置一个变量,并使其可用于其他阶段。在声明性管道中,似乎唯一的方法是在script {}块中。 例如,我需要在结帐后设置一些变量。因此,在结帐阶段结束时,我有一个script {}块来设置这些var,并且可以在其他阶段访问它们。 这可行,但感觉不对。并且出于可读性考虑,我更愿意在管道的顶部声明这些