How to POST request using axios with React Hooks?

Viewed 9245

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?

2 Answers

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:

  1. In your form you have to use the state(values) properties.
  2. 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.

Related