我目前正在学习使用上下文API进行react ,基本上我try 在上下文中使用State来判断用户是否使用简单的Boolean isAuthated State登录.问题是,尽管上下文对两个组件都可见,但对所述状态所做的任何更改都不会像使用上下文时那样反映到其他组件中.

这是我的代码,

AuthContext.js

import React, { createContext, useState } from 'react';

export const AuthContext = createContext();

export const AuthContextProvider = ({ children }) => {
    const [isAuthenticated, setIsAuthenticated] = useState(false);

    console.log("AuthCOntext", AuthContext);
  const contextValue = {
        isAuthenticated,
        // updateIsAuthenticated,
        setIsAuthenticated
    };

    return (
        <AuthContext.Provider value={contextValue}>
            {children}
        </AuthContext.Provider>
    );
};

LoginForm.js

import React, { useContext, useEffect, useState } from 'react';
import Button from 'react-bootstrap/Button';
import formStyles from '../../styles/form.module.css';

import { postLoginForm } from '../../helpers/RequestHelper';
import { AuthContext } from '../../contexts/AuthContext';

export default function LoginForm() {
    const { isAuthenticated, setIsAuthenticated } = useContext(AuthContext);

    const [returnedResponseState, setReturnedResponseState] = useState({
        status: 0,
        text: ''
    })



    async function submitLoginForm(event) {
        event.preventDefault();
        const form = event.target;
        const formData = new FormData(form);
        const actualFormData = Object.fromEntries(formData.entries());
        console.log(actualFormData);
        console.log("Before updateIsAuthenticated:", isAuthenticated);
        await postLoginForm(actualFormData).then(
            (res) => {
                console.log(res);
                if (!res) {

                }
                else {

                    setReturnedResponseState({ status: res.status, text: res.data }, () => {
                        console.log(returnedResponseState);
                    });

                    if (res.status === 200) {
                        setIsAuthenticated(true);
                    }
                }
            });
        console.log("after updateIsAuthenticated", isAuthenticated);
    }


    return (
        <div className={formStyles.formDiv} id='loginform'>
            {console.log(isAuthenticated)}
            <form onSubmit={submitLoginForm}>
                <h5>Login</h5>
                <div>
                    {returnedResponseState ? returnedResponseState.text : null}
                </div>
                <div className={formStyles.formElement}>
                    <label htmlFor="emailID" className={formStyles.formElementLabel}>Email ID</label>
                    <input type='email' name="emailID" placeholder="something@example.com"></input>
                </div>
                <div className={formStyles.formElement}>
                    <label htmlFor="Password1" className={formStyles.formElementLabel}>Password</label>
                    <input type="password" name="password1" placeholder="*****"></input>
                </div>
                <Button type='submit'> Log in</Button>
            </form>
        </div>
    )
}

Library.js

import React, { useState, useEffect, useContext } from 'react';
import Card from 'react-bootstrap/Card';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import { AuthContext } from '../../contexts/AuthContext';

import { getUserData } from '../../helpers/RequestHelper';

export default function Library() {
  const { isAuthenticated } = useContext(AuthContext);
  const [response, setResponse] = useState(null);

  useEffect(() => {
    async function getUserPageData() {
      const result = await getUserData();
      setResponse(result.playlist);
      console.log("Is authenticated", isAuthenticated);
    }

    getUserPageData();
  }, []); // Add isAuthenticated as a dependency

  return (
    <div>
      <div>
        <h5>Your Playlists</h5>
        <h6>playlist name</h6>
        <Row xs={1} md={2} lg={3} xl={3}>
          {response && response.length !== 0 ? (
            response.map((video) => (
              <Col>
                <Card>
                  <p>{video.title}</p>
                </Card>
              </Col>
            ))
          ) : (
            <p>You currently have no playlists created</p>
          )}
        </Row>
      </div>
    </div>
  );
}

Index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { AuthContextProvider } from './contexts/AuthContext';
import { Children } from 'react';


const root = ReactDOM.createRoot(document.getElementById('root'));
console.log(root);
root.render(
  <React.StrictMode>
    <AuthContextProvider value={Children}>
      <App />
    </AuthContextProvider>
  </React.StrictMode>
);

reportWebVitals();

App.js

import './App.css';
import {
  createBrowserRouter,
  Outlet,
  RouterProvider,
} from 'react-router-dom';
import Index from './components/Index';
import NavigationBar from './components/Navbar/NavigationBar';
import VideoPlayerPage from './views/VideoPlayerPage'
import AccountPage from './views/AccountPage';
import LoginSignupPage from './views/LoginSignupPage';
import Library from './components/Account/Library';
import UploadVideoForm from './components/Forms/UploadVideoForm';

const router = createBrowserRouter([
  {
    path: "/",
    element: <Index />
  },
  {
    path: "/watch/:videoId",
    element: <VideoPlayerPage />
  },
  {
    path: "/login",
    element: <LoginSignupPage />
  },
  {
    path: "/user/home",
    element: <AccountPage />
  },
  {
    path: "/library",
    element: <Library />
  },
  {
    path: "/upload",
    element: <UploadVideoForm />
  }
])


function App() {
  return (
    <>
      <NavigationBar />
      <RouterProvider router={router}>
        <Outlet />
      </RouterProvider>

    </>
  );
}

export default App;

我在这里可能错了,但我已经try 包装上下文函数是useEffect钩子来触发可能正在使用AuthContext的任何组件的重新呈现,到目前为止我无法找到答案,因为在我看来一切都是正确的,并且react 和开发人员控制台都没有引发任何错误,除非出现警告:来自useState()和useReducer()钩子的状态更新不支持第二个回调参数.要在呈现后执行副作用,请使用useEffect()在组件主体中声明它.

推荐答案

你正在错误地解构它.在库中这样做,这意味着从返回的数组中将第一个元素赋给isAuthenticated变量(使用方括号[])

const [isAuthenticated] = useContext(AuthContext);

在您在问题中共享的代码中,您使用大括号{}进行了此操作,这意味着从返回中获取属性isAuthenticated,因为它总是返回一个未定义的数组

const { isAuthenticated } = useContext(AuthContext);

在codesandbox中,您这样做了,这意味着将所有内容都赋给isAuthenticated,它始终是一个数组

const isAuthenticated = useContext(AuthContext);

另外,如果您在没有路由的情况下导航,例如,输入URL或按F5,所有状态都将被重置.我刚刚更新了您的代码,以便使用路由链接进行导航:

https://codesandbox.io/s/focused-shannon-3k667f?file=/src/LoginPage.js

Reactjs相关问答推荐

构建next.js项目时状态不变,但在dev服务器中

在Reaction常量函数中未更新状态变量

基本react 应用程序正在触发两次Use Effect

如何在NextJS中仅在刷新页面和页面淡出页面过渡时添加全屏加载器

当我try 部署我的Reaction应用程序时,为什么在此PrevState语句中收到语法错误?

如何使图像zoom 并移动到点击点

在url中使用MongoDB对象ID被认为是不好的做法?

状态更改是否卸载功能组件

定位数组中的一项(React、useState)

列表中的每个子项都应该有一个唯一的keyprops .在react 应用程序中

在React中使用if条件时如何更改Tailwind中元素的文本 colored颜色

React useEffect 依赖项

每次状态更改时都会提交react 表单

在 CrafterCMS Studio 中拖动字段

有没有办法在用户离开页面时防止输入模糊?

使用 map 循环浏览列表列表中的列表并显示它们

Primereact 的日历组件在每个月 12 日之后使用非唯一键生成

无法在 reactJS 中使用空包装器 <>

更新 Next.js 路由查询更改的状态会导致无限循环

React Native PermissionsAndroid 不包括 READ_MEDIA_IMAGES.如何解决这个问题?