我正在嘗試更新另一個組件正在使用的物件。
我的背景:
import React, {Component, createContext} from "react";
import jwt from 'jsonwebtoken';
const LOCAL_STORAGE_AUTH_TOKEN = 'authToken';
interface AuthenticatedUser {
username?: string;
guildName?: string;
guildId?: string;
}
interface AuthContextType {
authenticated: boolean; // to check if authenticated or not
user: AuthenticatedUser; // store user details
token: string; //jwt token
refreshToken: string; //jwt refresh token
handleAuthentication: (username: string, password: string) => Promise<void>; // handle login process
logout: () => Promise<void>; // log out the user
}
export const AuthContext = createContext<AuthContextType>({
authenticated: false, // to check if authenticated or not
user: {}, // store all the user details
token: '', // store all the user details
refreshToken: '', //jwt refresh token
handleAuthentication: (username: string, password: string): Promise<void> =>
Promise.resolve(), // handle login process
logout: (): Promise<void> => Promise.resolve(), // logout the user
});
AuthContext.displayName = 'AuthContext';
export class AuthProvider extends Component {
state = {
authenticated:false,
user: {},
token:'',
refreshToken:''
};
constructor(props: any) {
super(props);
const token = window.localStorage.getItem(LOCAL_STORAGE_AUTH_TOKEN) || '';
const jwtData = jwt.decode(token);
let user = {};
let authenticated = false;
let refreshToken = '';
if(jwtData && typeof jwtData !== 'string'){
authenticated = true;
user = {
username: jwtData.data?.username || '',
// TODO: Add the other sources too
}
}
this.state = {
authenticated,
user,
token,
refreshToken
}
}
handleAuthentication = async (username: string, password: string):Promise<void> => {
fetch(process.env.REACT_APP_API_ENDPOINT "users/login", {
method:"POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({username:username, password:password})
})
.then(response => response.json())
.then((data) => {
/*
This data is coming back correctly
*/
const user = {
username: data?.user.username,
guildName: data?.user.guild_information[0].guildName,
guildId: "123123"
}
this.setState({
authenticated: true,
user: user,
token: data?.token,
refreshToken: data?.refreshToken
})
window.localStorage.setItem(LOCAL_STORAGE_AUTH_TOKEN, data?.token)
//TODO: Also save token in localstorage
})
.catch((err) => {
console.log(err)
})
}
logout = async ():Promise<void> => {
//TODO: Log out the current user
}
render() {
const authProviderValue = {
...this.state,
handleAuthentication: this.handleAuthentication,
logout: this.logout
}
return (
<AuthContext.Provider value={authProviderValue}>
{this.props.children}
</AuthContext.Provider>
)
}
}
以及我使用它的 App 組件:
import React, {useContext} from "react";
import { useStyles} from "./style";
import {AuthContext, AuthProvider} from "../../context/UserContext";
import RoutesProvider from "./Routes";
import Login from "../Login";
export default function App() {
const classes = useStyles();
const { user } = useContext(AuthContext)
return (
<AuthProvider>
{typeof user.username !== "undefined" ? (
<div className={classes.content}>
<RoutesProvider />
</div>
):(
<Login />
)}
</AuthProvider>
)
}
還按照建議將 App 組件包裝在 AuthProvider 中:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import { SnackbarProvider } from 'notistack';
import { AuthProvider} from "./context/UserContext";
import './styles/index.css'
ReactDOM.render(
<React.StrictMode>
<AuthProvider>
<SnackbarProvider maxSnack={3}>
<App />
</SnackbarProvider>
</AuthProvider>
</React.StrictMode>,
document.getElementById('root')
);
如果我在 AuthContext 中更改它,它確實采用初始值。但是更新后它不會在 App 組件中更新。我有點困惑為什么這不能按預期作業。如果有人知道這是什么原因(或者我做錯了),請告訴我。目前除錯 5 小時...
uj5u.com熱心網友回復:
如果我正確理解您的問題,您會問:
“當您的 handleAuthentication 方法成功時,為什么您的用戶常量不會更新”
答案是因為您正在您的提供者之外初始化您的用戶常量。
在 index.tsx 中使用 AuthProvider 而不是像這樣的 App 組件:
<AuthProvider>
<App />
</AuthProvider>
或者在子組件中轉移您的背景關系邏輯
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/375630.html
標籤:javascript 反应 打字稿 反应钩子 反应上下文
上一篇:如何跳過導致例外的鏈式承諾?
