javascript - React Hooks 问题 : Unhandled Rejection (TypeError): Cannot read property 'signup' of undefined

标签 javascript reactjs react-hooks

我正在尝试实现来自 https://usehooks.com/ 的 useAuth Hook

使用Auth.js

// Hook (use-auth.js)

import React, { useState, useEffect, useContext, createContext } from "react";
import axios from 'axios';

//Credentials


const authContext = createContext();

// Provider component that wraps your app and makes auth object ...
// ... available to any child component that calls useAuth().
export function ProvideAuth({ children }) {
  const auth = useProvideAuth();
  return <authContext.Provider value={auth}>{children}</authContext.Provider>;
}

// Hook for child components to get the auth object ...
// ... and re-render when it changes.
export const useAuth = () => {
  return useContext(authContext);
};

// Provider hook that creates auth object and handles state
function useProvideAuth() {

  const [user, setUser] = useState(null);
  const API_URL = "http://localhost:1038";

  // Wrap any Firebase methods we want to use making sure ...
  // ... to save the user to state.
  const signin = (email, password) => {
    return firebase
      .auth()
      .signInWithEmailAndPassword(email, password)
      .then(response => {
        setUser(response.user);
        return response.user;
      });
  };

  const register = (username, email, password) => {
    return firebase
      .auth()
      .createUserWithEmailAndPassword(email, password)
      .then(response => {
        setUser(response.user);
        return response.user;
      });
  };

  const signup = async (data) => {
    const SIGNUP_ENDPOINT = `${API_URL}/wp-json/wp/v2/users/register`;
    let response = '';
    try {
        response = await axios({
            method: 'post',
            responseType: 'json',
            url: SIGNUP_ENDPOINT,
            data: data
          });
    } catch(e){
        console.log(e);
    }
    console.log(response);
  };

  const signout = () => {
    return firebase
      .auth()
      .signOut()
      .then(() => {
        setUser(false);
      });
  };

  const sendPasswordResetEmail = email => {
    return firebase
      .auth()
      .sendPasswordResetEmail(email)
      .then(() => {
        return true;
      });
  };

  const confirmPasswordReset = (code, password) => {
    return firebase
      .auth()
      .confirmPasswordReset(code, password)
      .then(() => {
        return true;
      });
  };

  // Return the user object and auth methods
  return {
    user,
    signin,
    signup,
    register,
    signout,
    sendPasswordResetEmail,
    confirmPasswordReset
  };
}

表单register.js

import Link from 'next/link';
import Layout from '../components/layout';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faEnvelope, faCheck, faLock, faUser } from '@fortawesome/free-solid-svg-icons'

import useForm from 'react-hook-form'
import { useAuth } from "../hooks/useAuth";


export default function Register(props) {

    // Get auth state and re-render anytime it changes
    const auth = useAuth();
    const { register, handleSubmit, watch, errors } = useForm();
    const onSubmit = data => { auth.signup(data) }

    return (
        <Layout>
            <div className="container mt-sm p-md">
                <div className="columns">
                    <div className="column">

                    </div>
                    <div className="column">
                        <form onSubmit={handleSubmit(onSubmit)}>
                        <div className="field">
                        <label className="label">Username</label>
                        <div className="control has-icons-left has-icons-right">
                            <input className="input is-success" type="text" placeholder="Username" name="username" ref={register({ required: true })}/>
                            <span className="icon is-small is-left">
                            <FontAwesomeIcon icon={faUser}/>
                            </span>
                            <span className="icon is-small is-right">
                            <FontAwesomeIcon icon={faCheck}/>
                            </span>
                        </div>
                        {errors.username && <p className="help is-danger">This username is invalid</p>}
                        </div>

                        <div className="field">
                        <label className="label">Email</label>
                        <div className="control has-icons-left has-icons-right">
                            <input className="input is-success" type="text" placeholder="Email" name="email" ref={register({ required: true , pattern: /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/})}/>
                            <span className="icon is-small is-left">
                            <FontAwesomeIcon icon={faEnvelope}/>
                            </span>
                            <span className="icon is-small is-right">
                            <i className="fas fa-exclamation-triangle"></i>
                            </span>
                        </div>
                        {errors.email && <p className="help is-danger">This email is invalid</p>}
                        </div>
                        <div className="field">
                        <label className="label">Password</label>
                            <div className="control has-icons-left">
                                <input className="input" type="password" placeholder="Password" name="password" ref={register({ required: true , pattern: /^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})/ })}/>
                                <span className="icon is-small is-left">
                                <FontAwesomeIcon icon={faLock}/>
                                </span>
                            </div>
                        </div>
                        {errors.password && <p className="help is-danger">This password is too weak</p>}
                        <div className="field">
                        <label className="label">Confirm Password</label>
                            <div className="control has-icons-left">
                                <input className="input" type="password" placeholder="Confirm Password" name="confirm_password" ref={register({ required: true , validate: (value) => { return value === watch('password')} })}/>
                                <span className="icon is-small is-left">
                                <FontAwesomeIcon icon={faLock}/>
                                </span>
                            </div>
                        </div>
                        {errors.confirm_password && <p className="help is-danger">This password do not match</p>}
                        <div className="field">
                        <div className="control">
                            <label className="checkbox">
                            <input type="checkbox" name="terms" ref={register({ required: true })}/>
                            I agree to the <Link href='/'><a>terms and conditions</a></Link>
                            </label>
                        </div>
                        </div>
                        {errors.terms && <p className="help is-danger">You must agree to the terms and conditions</p>}

                        <div className="field is-grouped">
                        <div className="control">
                            <button className="button is-link">Submit</button>
                        </div>
                        <div className="control">
                            <button className="button is-link is-light" type="submit">Cancel</button>
                        </div>
                        </div>
                    </form> 
                    </div>
                    <div className="column">

                    </div>
                </div>

            </div>
        </Layout>
    )
}

我在提交表单并调用 useAuth Hook 时遇到错误。

Unhandled Rejection (TypeError): Cannot read property 'signup' of undefined
onSubmit
./pages/register.js:15
  12 | // Get auth state and re-render anytime it changes
  13 | const auth = useAuth();
  14 | const { register, handleSubmit, watch, errors } = useForm();
> 15 | const onSubmit = data => { auth.signup(data) }
     | ^  16 | 
  17 | return (
  18 |  <Layout>

关于我哪里出错的任何想法。这个钩子(Hook)本来是要与 firebase 一起使用的,但我正在为 wordpress 修改它,所以现在只设置了注册功能。

布局.js

    import Head from 'next/head'
    import Link from 'next/link'
    import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
    import { faCoffee } from '@fortawesome/free-solid-svg-icons'
    import '../styles/styles.sass'
    import { ProvideAuth } from "../hooks/useAuth";

    export default ({ children }) => {

    const toggleStyles = (event) => {
    document.querySelector('#burger').classList.toggle('is-active')
    document.querySelector('#navbarmenu').classList.toggle('is-active')
     }

    return (
    <ProvideAuth>
    <div>
      <Head>
        <title>Quiz Client</title>
        <meta name="viewport" content="initial-scale=1.0, width=device- 
     width"/>
      </Head>
      <header>
        <nav className="navbar is-primary" role="navigation" aria- 
         label="main navigation">
          <div className="navbar-brand">
            <a className="navbar-item">
                    <FontAwesomeIcon icon={faCoffee} />
            </a>
            <a id="burger" onClick={toggleStyles} 
                role="button" className="navbar-burger burger" aria- 
       label="menu" aria-expanded="false" data-target="navbarmenu">
              <span aria-hidden="true"></span>
              <span aria-hidden="true"></span>
              <span aria-hidden="true"></span>
            </a>
          </div>
          <div id="navbarmenu" className="navbar-menu">
            <div className="navbar-start">
              <Link prefetch href="/">
                <a className="navbar-item">Home</a>
              </Link>
              <Link prefetch href="/elsewhere">
                <a className="navbar-item">Elsewhere</a>
              </Link>
            </div>

            <div className="navbar-end"> 
              <Link prefetch href="/login">
                <a className="navbar-item">Login</a>
              </Link>
              <Link prefetch href="/register">
                <a className="navbar-item">Register</a>
              </Link>           
            </div>
          </div>
        </nav>
      </header>
      {children}
      <footer className="footer">
        <div className="content has-text-centered">
          <span>I'm the footer</span>
        </div>
      </footer>
      </div>
      </ProvideAuth>
      )
      }

请原谅格式

最佳答案

您的 Register 组件未由您的 ProvideAuth 提供商包装。您只需稍微重新排列组件即可解决此问题

function RegisterForm(props) {

  // Get auth state and re-render anytime it changes
  const auth = useAuth();
  const { register, handleSubmit, watch, errors } = useForm();
  const onSubmit = data => { auth.signup(data) }

  return (
    <div className="container mt-sm p-md">
      {/* the rest of your form */}
    </div>
  )
}

export default function Register(props) {
  return (
    <Layout>
      <RegisterForm />
    </Layout>
  )
}

关于javascript - React Hooks 问题 : Unhandled Rejection (TypeError): Cannot read property 'signup' of undefined,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58844608/

相关文章:

javascript - 如何在 jQuery 中迭代 HashMap 列表

javascript - OnClick函数无法获取一个 block 的 'value'属性的值,但它可以获取另一个 block 的值

javascript - 我在将 Prop 从状态传递给 child 时遇到问题

reactjs - 是否可以创建 React Hook 工厂函数?

javascript - 自定义上下文菜单在 Mac 上的 Firefox 中不起作用

javascript - 在 webgl 中创建类似铅笔的主体

ios - NativeModules.MyNativeModule 在 iOS 的 React Native 0.61.2 中未定义

javascript - 我想在从 firebase-database 获取时间后运行一个计时器,如何在 React JS 中使用 setInterval() 将时间减少一秒

react-native - 在 subview 中水平滚动时,如何防止父 Flatlist 的垂直滚动?

javascript - Jasmine - 模拟 spy On.and.callFake http成功错误