我正在尝试实现https://usehooks.com/中的useAuth钩子
useAuth.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
};
}
form 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挂钩。
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>
关于我哪里出错了的任何想法。该钩子本来可以与firebase一起使用,但是我会在wordpress上对其进行修改,因此现在仅设置了注册功能。
Layout.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>
)
}
请原谅
答案 0 :(得分:1)
您的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>
)
}