I am writing unit test case for login.
I am unsure about how to test handle submit as it contains one of the service call in the form of getToken() method, it would be greate if someone can guide me through how to handle this situation.
export const getToken = (credentials) => {
const token = 'abccss';
if (
credentials.username === 'test#test.com' &&
credentials.password === '123'
) {
return token;
} else {
return null;
}
};
The above code fetches user name and password and sends it to login in handleSubmit() function
//all imports(loginservice,auth etc etc)
import './Login.scss';
const Login = () => {
const [email, setEmail] = useState('');
const [pwd, setPwd] = useState('');
const authCon = useContext(AuthContext);
const handleSubmit = (e) => {
e.preventDefault();
const token = getToken({ username: email, password: pwd });
if (token) {
authCon.login(token);
window.location.href = '/dashboard';
}
};
return (
<div className="div-login">
<div className="div-login-logo">
<img src={logo} alt="Logo"></img>
</div>
<div>
<form onSubmit={handleSubmit}>
<input
className="credentials-input"
type="email"
value={email}
placeholder="Email Address"
required
onChange={(e) => setEmail(e.target.value)}
/>
<input
className="credentials-input"
type="password"
value={pwd}
placeholder="Password"
required
onChange={(e) => setPwd(e.target.value)}
/>
<button className="login-button" type="submit">
Log In
</button>
</form>
</div>
</div>
);
};
export default Login;
Test Code
test('Submit shoud work successfully', () => {
const mockLogin = jest.fn();
const { getByRole } = render(<Login handleSubmit={mockLogin} />);
const login_button = getByRole('button');
fireEvent.submit(login_button);
expect(mockLogin).toHaveBeenCalledTimes(1);
});
expect(jest.fn()).toHaveBeenCalledTimes(expected)
Expected number of calls: 1
Received number of calls: 0
As I am new to React, help will be appreciated.
The actual issue is handleSubmit is not a props of Login component.
Also you can't test the internal methods of a component using React testing Library, you have to move the handleSubmit method to either parent component or a common file and pass it to the login component or import it so that you can mock the method and perform the test.
Move the getToken and handleSubmit to a common file like below,
common.ts
export const getToken = (credentials:any) => {
const token = 'abccss';
if (
credentials.username === 'test#test.com' &&
credentials.password === '123'
) {
return token;
} else {
return null;
}
};
export const handleSubmit = (e:any, email:string, pwd: string) => {
e.preventDefault();
const token = getToken({ username: email, password: pwd });
if (token) {
// authCon.login(token);
window.location.href = '/dashboard';
}
};
Modify Login.ts as like below ( see below handleSubmit is not internal and its imported from common.ts file so we that we can mock it)
import React, { useContext, useState } from 'react';
import { getToken, handleSubmit } from './common';
const Login = () => {
const [email, setEmail] = useState('');
const [pwd, setPwd] = useState('');
// const authCon = useContext(AuthContext);
return (
<div className="div-login">
<div className="div-login-logo">
{/* <img src={logo} alt="Logo"></img> */}
</div>
<div>
<form onSubmit={(e) => handleSubmit(e, email, pwd)}>
<input
className="credentials-input"
type="email"
value={email}
placeholder="Email Address"
required
onChange={(e) => setEmail(e.target.value)}
/>
<input
className="credentials-input"
type="password"
value={pwd}
placeholder="Password"
required
onChange={(e) => setPwd(e.target.value)}
/>
<button className="login-button" type="submit">
Log In
</button>
</form>
</div>
</div>
);
};
export default Login;
And finally Login.test.tsx shown below
import { fireEvent, render, screen } from '#testing-library/react';
import Login from './Login';
import * as CommonModule from './common';
jest.mock('./common');
test('Submit shoud work successfully', () => {
const mockLogin = jest.spyOn(CommonModule,'handleSubmit').mockImplementation();
const { getByRole } = render(<Login />);
const login_button = getByRole('button');
fireEvent.submit(login_button);
expect(mockLogin).toHaveBeenCalledTimes(1);
});
Test Result :
Related
this is my test for user registration using jest + react testing library, the problem is that the test update the db.
therefore at the second run the test fails (beacuse the first run registered the user)
so my question is anyone know how can I mock this function?
I will be grateful for any help I could get. thanks in advance
the test
test('signup should dispatch signupAction', async () => {
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
initialState = {
authReducer: { isAuthenticatedData: false },
};
const store = mockStore(initialState);
render(
<Provider store={store}>
<Router>
<UserSignup />
</Router>
</Provider>
);
const nameTextbox = screen.getByPlaceholderText('Name*');
const emailTextbox = screen.getByPlaceholderText('Email*');
const passwordTextbox = screen.getByPlaceholderText('Password*');
const confirmTextbox = screen.getByPlaceholderText('Confirm Password*');
const signupButton = screen.getByRole('button', { name: 'Register' });
userEvent.type(nameTextbox, 'newtestuser');
userEvent.type(emailTextbox, 'newtestuser#gmail.com');
userEvent.type(passwordTextbox, 'testuser123');
userEvent.type(confirmTextbox, 'testuser123');
userEvent.click(signupButton);
await waitFor(() => expect(store.getActions()[0].type).toBe('SIGNUP_SUCCESS'));
});
sign up component
const userSignup = () => {
const dispatch = useDispatch();
const isAuthenticatedData = useSelector((state) => state.authReducer.isAuthenticatedData);
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
re_password: '',
});
const [accountCreated, setAccountCreated] = useState(false);
const { name, email, password, re_password } = formData;
const onChange = (e) => setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = (e) => {
e.preventDefault();
if (password === re_password) {
try {
dispatch(
signupAction({
name,
email,
password,
re_password,
})
);
setAccountCreated(true);
} catch {
window.scrollTo(0, 0);
}
}
};
if (isAuthenticatedData) return <Redirect to='/' />;
if (accountCreated) return <Redirect to='/login' />;
return (
<div data-testid='userSignup'>
<h1>Sign Up</h1>
<p>Create your Account</p>
<form onSubmit={(e) => onSubmit(e)}>
<div>
<input
type='text'
placeholder='Name*'
name='name'
value={name}
onChange={(e) => onChange(e)}
required
/>
</div>
<div>
<input
type='email'
placeholder='Email*'
name='email'
value={email}
onChange={(e) => onChange(e)}
required
/>
</div>
<div>
<input
type='password'
placeholder='Password*'
name='password'
value={password}
onChange={(e) => onChange(e)}
minLength='6'
required
/>
</div>
<div>
<input
type='password'
placeholder='Confirm Password*'
name='re_password'
value={re_password}
onChange={(e) => onChange(e)}
minLength='6'
required
/>
</div>
<button type='submit'>Register</button>
</form>
<p>
Already have an account? <Link to='/login'>Sign In</Link>
</p>
</div>
);
};
export default connect()(userSignup);
sign up action
export const signupAction =
({ name, email, password, re_password }) =>
async (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const body = JSON.stringify({
name,
email,
password,
re_password,
});
try {
const res = await axios.post(`${process.env.REACT_APP_API_URL}/api/djoser/users/`, body, config);
dispatch({ type: SIGNUP_SUCCESS, payload: res.data });
} catch (err) {
dispatch({ type: SIGNUP_FAIL });
}
};
Assuming you are writing unit tests (which is probably where you should start), then you are looking for a concept called "mocking." The idea is that your React unit tests should only test your React code. Your React unit tests should not depend on a database or even an API. That introduces all sorts of challenges, as you have discovered.
Basically how mocking frameworks work is you configure them with some fake data. Then when you run the tests, your code uses that fake data instead of calling the API.
I see you are using axios to call your API. I suggest you check out axios-mock-adapter to help you mock those axios calls.
I managed to solve this problem here is the test for those who needs it
import '#testing-library/jest-dom/extend-expect';
import { render, screen } from '#testing-library/react';
import { Provider } from 'react-redux';
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import UserSignup from '../../../components/users/UserSignup';
import configureStore from 'redux-mock-store';
import { signupAction } from '../../../redux/actions/auth';
import thunk from 'redux-thunk';
import userEvent from '#testing-library/user-event';
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
let initialState = {
authReducer: {},
};
const store = mockStore(initialState);
jest.mock('../../../redux/actions/auth', () => ({ signupAction: jest.fn() }));
test('Redux - signup should dispatch signupAction', () => {
render(
<Provider store={store}>
<Router>
<UserSignup />
</Router>
</Provider>
);
initialState = {
authReducer: { isAuthenticatedData: false },
};
const store = mockStore(initialState);
render(
<Provider store={store}>
<Router>
<UserSignup />
</Router>
</Provider>
);
const nameTextbox = screen.getByPlaceholderText('Name*');
const emailTextbox = screen.getByPlaceholderText('Email*');
const passwordTextbox = screen.getByPlaceholderText('Password*');
const confirmTextbox = screen.getByPlaceholderText('Confirm Password*');
const signupButton = screen.getByRole('button', { name: 'Register' });
const nameValue = 'testuser';
const emailValue = 'testuser#gmail.com';
const passwordValue = 'testuser123';
const rePasswordValue = 'testuser123';
userEvent.type(nameTextbox, nameValue);
userEvent.type(emailTextbox, emailValue);
userEvent.type(passwordTextbox, passwordValue);
userEvent.type(confirmTextbox, rePasswordValue);
userEvent.click(signupButton);
const timesActionDispatched = signupAction.mock.calls.length;
expect(timesActionDispatched).toBe(1);
expect(signupAction.mock.calls[0][0].name).toEqual(nameValue);
expect(signupAction.mock.calls[0][0].email).toEqual(emailValue);
expect(signupAction.mock.calls[0][0].password).toEqual(passwordValue);
expect(signupAction.mock.calls[0][0].re_password).toEqual(rePasswordValue);
});
I am building Login and Signup pages using react and auth by using firebase.
The problem is that after successful login and signup, the application is NOT navigating the user to landing page.
I think there is something wrong with my handleLogin and handleSignup methods but, I'm to pinpoint it out.
To Login: use -> email: test#gmail.com and password: 123456
Also, there are no errors in the console and I get 200 response from firebase.
This is firebase.config.js
import firebase from "firebase";
var firebaseConfig = {
apiKey: "MY_KEY",
authDomain: "login-and-push-notification.firebaseapp.com",
projectId: "login-and-push-notification",
storageBucket: "login-and-push-notification.appspot.com",
messagingSenderId: "84083076850",
appId: "1:84083076850:web:3e9febc1341d8f7b036a6b",
};
// Initialize Firebase
const fb = firebase.initializeApp(firebaseConfig);
export default FB;
This is Login.js
const Login = (props) => {
const [user, setUser] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [emailError, setEmailError] = useState("");
const [passwordError, setPasswordError] = useState("");
const [hasAccount, setHasAccount] = useState(false);
const clearInputs = () => {
setEmail("");
setPassword("");
};
const clearErrors = () => {
setEmailError("");
setPasswordError("");
};
const handleLogin = () => {
clearErrors();
fb.auth()
.signInWithEmailAndPassword(email, password)
.then((user) => {
console.log("user", user);
props.navigation.push("/Landing");
})
.catch((error) => {
switch (error.code) {
case "auth/invalid-email":
case "auth/user-disabled":
case "auth/user-not-found":
setEmailError(error.message);
break;
case "auth/wrong-password":
setPasswordError(error.message);
break;
}
});
};
const handleSignup = () => {
clearErrors();
fb.auth()
.createUserWithEmailAndPassword(email, password)
.catch((error) => {
switch (error.code) {
case "auth/email-already-in-use":
case "auth/invalid-email":
setEmailError(error.message);
break;
case "auth/weak-password":
setPasswordError(error.message);
break;
}
});
};
const authListener = () => {
fb.auth().onAuthStateChanged((user) => {
if (user) {
clearInputs();
setUser(user);
} else {
setUser("");
}
});
};
useEffect(() => {
authListener();
}, []);
return (
<div className="login">
<div className="loginContainer">
<label>Username</label>
<input
type="text"
value={email}
autoFocus
required
onChange={(e) => setEmail(e.target.value)}
/>
<p className="errorMsg">{emailError}</p>
<label>Password</label>
<input
type="password"
value={password}
required
onChange={(e) => setPassword(e.target.value)}
/>
<p className="errorMsg">{passwordError}</p>
<div className="btnContainer">
{hasAccount ? (
<span>
<button onClick={handleLogin} type="submit">
Sign In
</button>
<p>
Don't have an account?
<span onClick={() => setHasAccount(!hasAccount)}>Sign up</span>
</p>
</span>
) : (
<>
<button onClick={handleSignup} type="submit">
Sign Up
</button>
<p>
Have an account?
<span onClick={() => setHasAccount(!hasAccount)}>Sign in</span>
</p>
</>
)}
</div>
</div>
</div>
);
};
And then I'm importing the Login component into the Home component and passing props.
import React from "react";
import Login from "../components/Login";
import Landing from "../Pages/Landing";
function Home(props) {
return (
<div>{props.user ? <Landing {...props} /> : <Login {...props} />}</div>
);
}
export default Home;
Your authListener() in Login.js is setting a state variable in the Login component, but it does not communicate the change of state back to the rest of the application.
One way to resolve this would be to move the const [user, setUser] = useState() from Login.js to Home.js, then pass setUser as a prop to <Login>. That way, when the onAuthStateChanged() gets the user object, you set it in state at the Home level.
You'd additionally change the condition statement in Home.js to be:
return (
<div>{user ? <Landing {...props} /> : <Login {...props} />}</div>
);
since user would now be a state variable in Home.js.
Once you have that working and are comfortable with it, you might consider moving all of your authentication handling into a pattern that leverages useContext(). You would create an AuthProvider component. There are several blogs on this topic, such as this one
App Component:
import LoginForm from "./Component/LoginForm/LoginForm";
import HomePage from "./Component/HomePage/HomePage";
import { useState, useEffect } from "react";
function App() {
const user = [{ username: "admin" }, { password: "admin" }];
const [isLoggedIn, setIsLoggedIn] = useState(false);
useEffect(() => {
const isUserLoggedIn = localStorage.getItem("isLoggedInn");
if (isUserLoggedIn === "1") {
setIsLoggedIn(true);
}
}, []);
const loginHandler = () => {
localStorage.setItem("isLoggedInn", "1");
setIsLoggedIn(true);
};
const logoutHandler = () => {
localStorage.removeItem("isLoggedInn");
setIsLoggedIn(false);
};
// const saveData = (enteredUsername, enteredPassword) => {
// const userPassData = {
// 'username':enteredUsername,
// 'password':enteredPassword
// };
// return userPassData;
// }
return (
<div>
{!isLoggedIn && <LoginForm adminUser={user} onLogin={loginHandler} />}
{isLoggedIn && <HomePage onLogout={logoutHandler} />}
</div>
);
}
export default App;
LoginForm Component:
import styles from './LoginForm.module.css';
import { useState } from 'react';
import SignUp from '../SignUp/SignUp';
const LoginForm = (props) =>{
const [enteredUsername,setEnteredUsername] = useState('');
const [enteredPassword,setEnteredPassword] = useState('');
const [isTrue,setTrue] = useState(true);
const [isClicked,setIsClicked] = useState(false);
const onChangeHandlerUsername = event =>{
setEnteredUsername(event.target.value);
if(event.target.value === enteredUsername){
setTrue(true);
}
}
const onChangeHandlerPassword = event =>{
setEnteredPassword(event.target.value);
if(event.target.value === enteredPassword){
setTrue(true);
}
}
const onSubmitHandler = (event) =>{
event.preventDefault();
if(enteredUsername === props.adminUser[0].username && enteredPassword === props.adminUser[1].password){
props.onLogin();
console.log(enteredUsername,enteredPassword);
}
else{
setTrue(false);
setIsClicked(true);
}
}
const onClickHandler =()=>{
setIsClicked(true);
}
return(
<>
<form onSubmit={onSubmitHandler}>
<h1>Welcome</h1>
<div className={`${styles.box} ${!isTrue && styles.wrong}`}>
<h1>Login</h1>
<input type='text' value={enteredUsername} placeholder='Enter Username' className={styles.email} onChange={onChangeHandlerUsername}></input>
<input type='password' value={enteredPassword} placeholder='Enter Password' className={styles.email} onChange={onChangeHandlerPassword}></input>
<div><button className={styles.btn}>Sign In</button></div>
<div><button onClick={onClickHandler} type='button' className={styles.btn2}>Sign Up</button></div>
<div><a href='#top'>Forget Password</a></div>
</div>
</form>
{!isClicked? '' :<SignUp/>}
</>
);
}
export default LoginForm;
want to go to SignUp page when clicked on SignUp from the App component in React can some one rectify the code accordingly. Dont know where i am wrong can some one help me out.
There is SignUp button which when clicked based on the username and password if not same as that of the added user or Admin will go to the sign up page to register for the new user.
SignUp component:
import './SignUp.module.css';
const SignUp = (props) =>{
return(
<div>
<h2>SignUp page</h2>
</div>
);
}
export default SignUp;
you are having your SignUp below the Form component if you need to render only one of them based on the isClicked then you can use the ternary operator to do it.
change your code as below
<>
{isClicked ? (
<SignUp />
) : (
<form onSubmit={onSubmitHandler}>
<h1>Welcome</h1>
<div>
<h1>Login</h1>
<input
type="text"
value={enteredUsername}
placeholder="Enter Username"
onChange={onChangeHandlerUsername}
></input>
<input
type="password"
value={enteredPassword}
placeholder="Enter Password"
onChange={onChangeHandlerPassword}
></input>
<div>
<button>Sign In</button>
</div>
<div>
<button onClick={onClickHandler} type="button">
Sign Up
</button>
</div>
<div>
Forget Password
</div>
</div>
</form>
)}
</>
Also you should not be doing this
const onChangeHandlerUsername = event =>{
setEnteredUsername(event.target.value);
// This will always be false because the state change wont reflect immediately.
// Please remove this for both the username and password
if(event.target.value === enteredUsername){
setTrue(true);
}
}
I am trying to submit a POST form with a simple html form and I also use redux with a userAction which allows to store the user and the token returned by the express js API, but the submission does not work, when I submit the form, nothing happens I can't even get into the fetch function of the action.
import '../styles/ConnexionModal.css';
import { userLogin } from '../redux/userActions';
import { useState } from 'react';
// import { useSelector } from 'react-redux';
const ConnexionModal = ({ showModal, hideModal }) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
// const message = useSelector(state => state.userReducer.message);
// console.log(message);
const handleChangeEmail = (event) => {
setEmail(event.target.value);
}
const handleChangePassword = (event) => {
setPassword(event.target.value);
}
const handleSubmit = (e) => {
e.preventDefault();
userLogin(email, password);
}
return (
showModal && (
<div className="modalBg">
<div className="modalContainer">
<div className="modalHeader">
<h1 className="modalTitle">Connexion</h1>
</div>
<div className="modalBody">
<form method="POST" onSubmit={handleSubmit}>
<div className="formGroup">
<label htmlFor="email" className="info">Email</label>
<input className="field" name="email" id="email" type="email" value={email} onChange={handleChangeEmail} autoFocus required />
</div>
<div className="formGroup">
<label htmlFor="password" className="info">Mot de passe</label>
<input className="field" name="password" id="password" type="password" value={password} onChange={handleChangePassword} required />
</div>
<div className="formGroup">
<label htmlFor="connexion" className="submitButton">Se connecter</label>
<input className="field submit" id="connexion" name="submit" type="submit" />
</div>
</form>
</div>
<div className="close">
<button onClick={() => hideModal()} className="closeButton">Fermer</button>
</div>
</div>
</div>
)
)
}
export default ConnexionModal;
export const LOGIN = "LOGIN";
export const ERROR = "ERROR";
export const userLogin = (email, password) => {
return async dispatch => {
console.log('test');
fetch('http://192.168.1.36:4000/api/users/login', {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
email: email,
password: password
})
})
.then((res) => res.json())
.then(async (res) => {
if(!res.error) {
localStorage.setItem('auth', res.token);
dispatch({ type: LOGIN, user: res.user, token: res.token });
} else {
dispatch({ type: ERROR, message: res.error });
}
})
}
}
The console.log ('test') does not display anything which means I am not even accessing the userLogin function in my component.
I assume you are also using redux-thunk.
You should always pass the action inside your container to a redux dispatch function. E.g.
import '../styles/ConnexionModal.css';
import { userLogin } from '../redux/userActions';
import { useState } from 'react';
import { useDispatch } from 'react-redux';
const ConnexionModal = ({ showModal, hideModal }) => {
const dispatch = useDispatch();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleChangeEmail = (event) => {
setEmail(event.target.value);
}
const handleChangePassword = (event) => {
setPassword(event.target.value);
}
const handleSubmit = (e) => {
e.preventDefault();
dispatch(userLogin(email, password));
}
...
This is my Signupcomponent
const SignupComponent = () => {
const [values, setValues] = useState({
username: 'silvio1',
name: 'Silvioo',
email: 'berlusconi#gmail.com',
password: '123ooo007',
});
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
const { username, name, email, password } = values;
const user = {username, name, email, password};
await axios.post('${API)/signup', user);
};
const handleChange = name => e => {
setValues({ ...values, [name]: e.target.value });
};
const showLoading = () => (loading ? <div className="alert alert-info">Loading...</div> : '');
const signupForm = () => {
return (
<form onSubmit={handleSubmit}>
<div className="form-group">
<input
value={values.username}
onChange={handleChange('username')}
type="text"
className="form-control"
placeholder="Type your username"
/>
</div>
<div className="form-group">
<input
value={values.name}
onChange={handleChange('name')}
type="text"
className="form-control"
placeholder="Type your name"
/>
</div>
<div className="form-group">
<input
value={values.email}
onChange={handleChange('email')}
type="email"
className="form-control"
placeholder="Type your email"
/>
</div>
<div className="form-group">
<input
value={values.password}
onChange={handleChange('password')}
type="password"
className="form-control"
placeholder="Type your password"
/>
</div>
<div>
<button className="btn btn-primary">Signup</button>
</div>
</form>
);
};
return <React.Fragment>
{showLoading()}
{signupForm()}
</React.Fragment>;
};
export default SignupComponent;
EDIT
I changed my code(zhulien's accepted answer).
Signup page appears,I try to sign up user.
I got error
Unhandled Runtime Error
Error: Request failed with status code 404
Call Stack
createError
node_modules/axios/lib/core/createError.js (16:0)
settle
node_modules/axios/lib/core/settle.js (17:0)
XMLHttpRequest.handleLoad
node_modules/axios/lib/adapters/xhr.js (62:0)
Frontend folder
components
config.js
next.config.js
node_modules
package.json
package-lock.json
pages
My pages folder
_document.js
index.js
signin.js
signup.js
signup.js imports the code above
import Link from 'next/link';
import Layout from '../components/Layout';
import SignupComponent from '../components/frontauth/SignupComponent';
const Signup = () => {
return (
<Layout>
<h2>Signup page</h2>
<SignupComponent />
</Layout>
);
};
My next.config.js
{
APP_NAME: 'BLOG FRONTEND',
APP_DEVELOPMENT: 'http://localhost:3000',
PRODUCTION: false
}
And config.js
const { publicRuntimeConfig } = getConfig();
console.log(publicRuntimeConfig);
export const API = publicRuntimeConfig.PRODUCTION
? 'https://cryptoblog.com'
: 'http://localhost:3000';
export const APP_NAME = publicRuntimeConfig.APP_NAME;
I am new to React and React Hooks. How to solve this problem?
First of all, you're trying to access {username}(which doesn't exist) instead of the state property which is values.username. Furthermore, don't use hooks in event handlers, they should be used in the top level body of the component or in custom hooks only. Checkout this: React hooks rules.
So:
In your form you have to use the state(values) properties.
Extract useEffect hook in the main body flow of the component or BETTER remove it altogether as you're not using it properly currently. You're better of with just the simple event handler for form submit which should post the data somewhere without setting any state.
Your code could look something like:
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { API } from '../../config';
const SignupComponent = () => {
const [values, setValues] = useState({
username: 'silvio1',
name: 'Silvioo',
email: 'berlusconi#gmail.com',
password: '123ooo007',
});
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
const { username, name, email, password } = values;
const user = {username, name, email, password};
await axios.post('${API)/signup', user);
};
const handleChange = name => e => {
setValues({ ...values, [name]: e.target.value });
};
const showLoading = () => (loading ? <div className="alert alert-info">Loading...</div> : '');
const signupForm = () => {
return (
<form onSubmit={handleSubmit}>
<div className="form-group">
<input
value={values.username}
onChange={handleChange('username')}
type="text"
className="form-control"
placeholder="Type your username"
/>
</div>
this is how it should be:
useEffect(() => {
postUser();
}, []);
not inside the function the way you have done it:
const handleSubmit = e => {
e.preventDefault();
setValues({...values});
const { username, name, email, password } = values;
const user = {username, name, email, password};
async function postUser () {
const result = await axios.post('${API)/signup', user);
};
useEffect(() => {
postUser();
}, []);
};
UseEffects aren't meant to be placed inside your functions.Just place them inside your functional component,with some value(or no value) inside your dependency array of the useEffect.These values present inside the array will trigger the useEffect whenever they get changed.