javascript useState inside event onClick无效的钩子调用,钩子只能在函数组件的主体内部调用

e3bfsja2  于 2023-05-05  发布在  Java
关注(0)|答案(1)|浏览(104)

我有一个应用程序,其中我使用React钩子,useState,useEffect,useContext我有1页Login.js和loginStoreContext.js文件
Login.js im渲染一个带有按钮的基本表单,该按钮具有onClick,该按钮采用导出的SigninWithGoogle函数

import React,{useContext} from 'react'
import Body from '../../UI/Card/Body';
import {Form } from 'react-bootstrap';
import MainButton from '../../UI/Button/Button';
import {SigninWithGoogleProvider} from '../../store/loginStoreContext'
const Login = () => {
  return (
    <Body>
      <Form>
        <Form.Group className="mb-3" controlId="exampleForm.ControlInput1">
          <Form.Label>Email address</Form.Label>
          <Form.Control type="email" placeholder="name@example.com" />
        </Form.Group>

        <Form.Group className="mb-3" >
          <Form.Label htmlFor="inputPassword5">Password</Form.Label>
          <Form.Control
            type="password"
            id="inputPassword5"
            aria-describedby="passwordHelpBlock"
          />
          <Form.Text id="passwordHelpBlock" muted>
            Your password must be 8-20 characters long, contain letters and numbers,
            and must not contain spaces, special characters, or emoji.
          </Form.Text>
        </Form.Group>
      </Form>
       <button type="button" onClick={SigninWithGoogleProvider}>Signin with Google</button>
    </Body>
  )
}

export default Login

SigninWithGoogle.js在这里我只是想在我的React应用程序中使用谷歌登录

import React , {createContext,useState} from "react";
import app from '../firebaseConfig';
import { GoogleAuthProvider, getAuth, signInWithPopup } from "firebase/auth";

export const AppContext = createContext({
    user:{},
    token:'',
})

export const SigninWithGoogleProvider = (props)=>{

    const [userdata,setUserData] =useState({})
    const [token,setToken] = useState('')

    const provider = new GoogleAuthProvider();
    const auth = getAuth(app)

    signInWithPopup(auth,provider)
    .then(result=>{
       // This gives you a Google Access Token. You can use it to access Google APIs.
    const credential = GoogleAuthProvider.credentialFromResult(result);
    const userToken = credential.accessToken;
    
    setToken(userToken)
    // The signed-in user info.
    const user = result.user;
    setUserData(user)
    })
    .catch(error=>{
      console.log(error)
    })

    return <AppContext.Provider value={{
        user:userdata,
        token:token
    }}>
        {props.children}
    </AppContext.Provider>
  }

经过研究,我知道我不能在事件内部使用钩子,如果我注解useState,代码将工作,但我需要在上下文中管理状态,这样我就可以在任何地方访问我的Auth用户,有没有一个工作解决方案可以帮助这个问题?
我试图研究的问题后,研究我来知道,我不能使用useState与事件,但我需要有他们这样来管理我的状态,我不能保持它在组件内

pkwftd7m

pkwftd7m1#

从你写的内容来看,似乎不需要Context,你只需要将数据从父组件传递给子组件,以及一个更改回调。
这是你的代码的简化,但我认为这足以让你理解。如果你不明白什么或者你想要更深层次的答案,请告诉我。

const Login = () => {
  const [userdata, setUserData] = useState({});
  const [token, setToken] = useState("");

  const updateStates = (newUserData, newToken) => {
    setUserData(newUserData);
    setToken(newToken);
  };

  return (
    <Body>
      <Form>{/* Whatever you want to render here */}</Form>
      <SigninWithGoogleProvider
        userData={userData}
        token={token}
        updateStates={updateStates}>
        <button type="button">Signin with Google</button>
      </SigninWithGoogleProvider>
    </Body>
  );
};

const SigninWithGoogleProvider = (props) => {
  const provider = new GoogleAuthProvider();
  const auth = getAuth(app);

  signInWithPopup(auth, provider).then((result) => {
    // This gives you a Google Access Token. You can use it to access Google APIs.
    const credential = GoogleAuthProvider.credentialFromResult(result);
    const userToken = credential.accessToken;

    props.updateStates(result.user, userToken);
  });

  return <>{props.children}</>;
};

我在这里所做的是“提升状态”,正如REACT文档中所建议的那样:https://react.dev/learn/sharing-state-between-components#lifting-state-up-by-example
基本上,您将数据保存在父组件中,然后将数据传递给子组件。此外,您还向子进程传递了一个回调,该回调允许更新父进程的状态。

相关问题