#javascript #reactjs #react-context #react-state-management
#язык JavaScript #реагирует на #реагировать-контекст #реагировать-государственное управление
Вопрос:
Я использую React для создания страницы входа в систему, которая после входа в систему должна отслеживать, вошел ли пользователь в систему. Я решил, что использовать контекст и состояние реакции будет проще, чем использовать что-то такое большое и сложное, как Redux.
Я создал функцию входа в систему, которая работает, и после успешного входа в систему она должна обновить мое состояние в моем контексте. Вход в систему работает (я получаю статус 200), но мое состояние не обновляется в моем контексте.
Мой «AuthContext.jsx» выглядит так
import React, { createContext, useState } from "react"; import { login, register } from "../API/apiMethods"; export const AuthContext = createContext(); export const AuthProvider = ({ children }) =gt; { const [authenticated, setAuthenticated] = useState(false); const authSetter = (state) =gt; { setAuthenticated(state); }; const authGetter = () =gt; { return authenticated; }; return ( lt;AuthContext.Provider value={{ authSetter, authGetter, login, register, }} gt; {children} lt;/AuthContext.Providergt; ); };
Моя функция входа в систему выглядит следующим образом
/** * @description Handles login * @param {String} email * @param {String} password * @returns {Boolean} */ export const login = async(email, password) =gt; { try { let authenticated = false; await fetch(BASE_URL "login", { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }), }).then((res) =gt; { authenticated = res.status === 200 ? true : false; }); return authenticated; } catch (err) { console.log(err); return false; } };
И в своей форме входа в систему я пытаюсь обновить логическое значение аутентификации после успешного входа в систему
const { login, authSetter, authGetter } = useContext(AuthContext); const submit = async(e) =gt; { e.preventDefault(); await login(email, password) .then((authSuccess) =gt; { if (authSuccess) { console.log("login successfull"); authSetter(true); } }) .then(() =gt; console.log(authGetter())); };
С помощью этого кода я ожидал, что вывод консоли будет печатной строкой с «успешно вошел в систему» и печатным логическим значением true. Но, похоже, мое состояние не было обновлено, хотя я и позвонил сеттеру.
Я не знаю, почему он не обновляется, может ли кто-нибудь мне помочь?
Комментарии:
1.
setAuthenticated
является асинхронной функцией,т. е. она не обновляется немедленно, поэтому вы получаете ложь в журнале. Попробуйте записать значение внеsubmit
функции
Ответ №1:
Этот фрагмент кода делает именно то, что он должен делать. Когда вы обновляете состояние, это происходит не сразу.
const submit = async(e) =gt; { e.preventDefault(); await login(email, password) .then((authSuccess) =gt; { if (authSuccess) { console.log("login successfull"); authSetter(true); } }) .then(() =gt; console.log(authGetter())); };
Когда вы вызываете authSetter(true);
, обновление состояния ставится в очередь, и как только обратный вызов завершается, оно переходит к следующему then
в цепочке, у которого есть ваш authGetter()
. Теперь обновление состояния происходит не сразу, как я объяснил, оно ставится в очередь. Поэтому, когда выполняется последний then
обратный вызов, обновление состояния, поставленное в очередь, не произошло, и вы все еще видите false
, какое значение является старым.
Вы можете выполнить рефакторинг AuthProvider
следующим образом: нет необходимости заключать сеттер в функцию, так как это создаст новый экземпляр функции при обновлении состояния ( useState
с другой стороны, возвращает запомненное значение функции сеттера), и вы можете просто вернуть authenticated
состояние без геттера, у которого снова та же проблема.
import React, { createContext, useState } from "react"; import { login, register } from "../API/apiMethods"; export const AuthContext = createContext(); export const AuthProvider = ({ children }) =gt; { const [authenticated, setAuthenticated] = useState(false); return ( lt;AuthContext.Provider value={{ setAuthenticated, authenticated, login, register, }} gt; {children} lt;/AuthContext.Providergt; ); };
В своей форме вы можете дополнительно useEffect
проверить, успешно ли вы вошли в систему. он useEffect
будет запущен, когда authenticated
состояние будет обновлено.
const { login, setAuthenticated, authenticated } = useContext(AuthContext); const submit = async(e) =gt; { e.preventDefault(); const authSuccess = await login(email, password); if (authSuccess) { console.log("login successfull"); authSetter(true); } }; useEffect(() =gt; { console.log(authenticated); }, [authenticated]);