使用 useContext 更新父组件

Updating Parent Component using useContext

我正在尝试从子组件更改父组件的状态。我的Component结构基本是这样的

<Admin>
    <Nav/> //Nav Bar
    {changePass && props.children} //Change Password Form
</Admin>

我的 Nav 依次有几个子组件:

  <NavBar>

    <NavItem menu="☰">
      <DropdownMenu/>
    </NavItem>
    
  </NavBar>

在DropdownMenu 组件中有子按钮Components、Logout、Delete Account 和Change Password。后者是我想在 Admin.tsx 中切换更改密码组件的地方。在 DropdownItem.tsx 我有一些代码来检测按钮点击:

//ChangePassContext.tsx
import { createContext } from "react";

export let ChangePassContext = createContext<boolean>(false)

 //DropdownItem.tsx
import { ChangePassContext } from "../Context/ChangePasswordContext/ChangePassContext";

 let changePass = useContext(ChangePassContext)

 //When window loads, get previous state from local storage
 if (destination === CHANGEPSSWD){
      if (localStorage.getItem('changePass') === "true"){
        changePass = !changePass
      } 
    }

    const handleMenu = (event: MouseEvent) => {
      event.preventDefault();
      if (destination === CHANGEPSSWD) {
   
        // Open Change Password Form
        if (changePass === false){
          localStorage.setItem('changePass', "true")
        } else {
          localStorage.removeItem('changePass')
        }
          changePass = !changePass
          console.log(changePass)
          window.location.reload() //I'll reference this in a moment
       } 
    }

然后我在我的 Admin.tsx 文件中调用 changePass 并使用我在本地存储中存储的内容更新它:

let changePass = useContext(ChangePassContext)
if (localStorage.getItem("changePass") === "true"){
  changePass = !changePass
}

并且如上所示,changePass 上下文控制 ChangePassword Form 是打开还是关闭:

{changePass && props.children} //Change Password Form

唯一的问题是我无法将状态从我的 DropdownItem 组件更新到我的 Admin 父组件。我可以让它更新的唯一方法是重新加载页面,就像我在 DropdownItem 组件中所做的那样,这会导致非常糟糕的用户体验:

具有讽刺意味的是,如您所见,我有一个可用的菜单组件(将 props 传递给子项似乎更容易),并且我使用 useContext 提供程序和 useState 完成了它。问题是,当我尝试使用 useState 设置上下文时,上下文不会更新,我不知道为什么。最初我尝试将我的 DropdownItem 函数设置为像这样简单的东西:

  if (destination === CHANGEPSSWD) {
    // Open Change Password Form
    setChangePass(!changePass)
  } 

我也根本不想使用 localStorage,但没有它我似乎无法使用 useContext。

我很沮丧,尤其是这段代码有多难看。希望有人能帮忙。

像这样制作您的管理文件:

//Admin.tsx
import { createContext } from "react";
export const ChangePassContext = createContext();

function App() {
 const[changePass, setChangePass] = useState({});

 return (
  <ChangePassContext.Provider value={[changePass, setChangePass]}>
  <Admin>
    <Nav/> //Nav Bar
    {changePass && props.children} //Change Password Form
  </Admin>
  </UserContext.Provider>
  );
 }

export default App;

然后你就可以在你的DropdownItem.tsx

中使用它了
//DropdownItem.tsx
import { useContext } from 'react';
import { ChangePassContext } from '../../App';
const DropdownItem = () => {
const[changePass, setChangePass]= useContext(ChangePassContext);
if (destination === CHANGEPSSWD) {
  // Open Change Password Form
  setChangePass(!changePass)
}
return (
   //your code
  );
};