How to use useFormik hook with async await in onSubmit event? - reactjs

I'm trying to find how to use async-await with useFormik hooks in onSubmit event.
I want to use axios library inside onSubmit event but with async await, but I'm not able to find the way how to use async await inside onSubmit event.
import React from 'react';
import { useFormik } from 'formik';
const SignupForm = () => {
const formik = useFormik({
initialValues: {
firstName: '',
lastName: '',
email: '',
},
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
name="firstName"
type="text"
onChange={formik.handleChange}
value={formik.values.firstName}
/>
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
value={formik.values.lastName}
/>
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
value={formik.values.email}
/>
<button type="submit">Submit</button>
</form>
);
};

The onSubmit event receives a callback function, it can be a normal function or async function:
...
onSubmit: async (values) => {
// await something here...
},
...

Declare your "await" inside onSubmit function, and then call the api using axios after "await" keyword.
EXAMPLE: https://codesandbox.io/s/jovial-wescoff-uh2e3b
CODE:
import React from "react";
import ReactDOM from "react-dom";
import { Formik, Field, Form } from "formik";
import axios from "axios";
const Example = () => (
<div>
<h1>Sign Up</h1>
<Formik
initialValues={{
firstName: "",
lastName: "",
email: "",
password: ""
}}
onSubmit={async (values) => {
const user = await axios.get("https://reqres.in/api/login", {
email: values.email,
password: values.password
});
alert(JSON.stringify(user, null, 2));
}}
>
{({ isSubmitting }) => (
<Form>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" placeholder="Eve" />
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" placeholder="Holt" />
<label htmlFor="email">Email</label>
<Field name="email" placeholder="eve.holt#reqres.in" type="email" />
<label htmlFor="password">Password</label>
<Field name="password" placeholder="cityslicka" type="password" />
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</Form>
)}
</Formik>
</div>
);
ReactDOM.render(<Example />, document.getElementById("root"));

Related

unable to use fetch in formik and post data to api

I was trying to post the formik form data using fetch and mutations. I have created my API using neo4j graphql library and Apollo server now i want to post data into the API using react as frontend.
import './App.css';
import { useFormik } from "formik"
function App() {
const updateNameFetch = async (name,age,sex,weight,smoking,drinking,nationality,birth_type) => {
const query = JSON.stringify({
query: `mutation {
createUsers(input:{
user_name: "${name}"
age: ${age}
sex: "${sex}"
weight: ${weight}
smoking:"${smoking}"
drinking: "${drinking}"
nationality:"${nationality}"
birth_type: "${birth_type}"
}
){
users{
user_name
}
}
}
`
});
const formik = useFormik({
initialValues:{
name:"",
age: "",
sex: "",
weight:"",
smoking:"",
drinking:"",
nationality:"",
birth_type:"",
},
onSubmit:(values) => {
console.log(values.name);
fetch("graphql-newone.herokuapp.com/",{
method: "POST",
headers: {"Content-Type": "application/json"},
body: query,
})
}
})
return (
<div className="App">
<form onSubmit={formik.handleSubmit}>
<div className='input-container'>
<input
id="name"
name="name"
type="text"
placeholder="Name"
onChange={formik.handleChange}
value = {formik.values.name}
/>
<input
id="sex"
name="sex"
type="text"
placeholder="Sex"
onChange={formik.handleChange}
value = {formik.values.sex}
/>
<input
id="age"
name="age"
type="text"
placeholder="Age"
onChange={formik.handleChange}
value = {formik.values.age}
/>
<input
id="weight"
name="weight"
type="text"
placeholder="weight"
onChange={formik.handleChange}
value = {formik.values.weight}
/>
<input
id="smoking"
name="smoking"
type="text"
placeholder="smoking"
onChange={formik.handleChange}
value = {formik.values.smoking}
/>
<input
id="nationality"
name="nationality"
type="text"
placeholder="nationality"
onChange={formik.handleChange}
value = {formik.values.nationality}
/>
<input
id="birth_type"
name="birth_type"
type="text"
placeholder="birth_type"
onChange={formik.handleChange}
value = {formik.values.birth_type}
/>
</div>
<button type="submit">Submit</button>
</form>
</div>
);
}}
export default App;
I am getting this error and unable to rectify it
Line 28:18: React Hook "useFormik" is called in function "updateNameFetch" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use" react-hooks/rules-of-hooks
Search for the keywords to learn more about each error.
As it says, you cant use the useFormik hook inside the function
import './App.css';
import { useFormik } from "formik"
function App() {
const postData = async(query)=>{
let res = await fetch("graphql-newone.herokuapp.com/",{
method: "POST",
headers: {"Content-Type": "application/json"},
body: query,
})
let data = await res.json()
console.log(data)
}
const formik = useFormik({
initialValues:{
name:"",
age: "",
sex: "",
weight:"",
smoking:"",
drinking:"",
nationality:"",
birth_type:"",
},
onSubmit:async(values) => {
let query = JSON.stringify({
query: `mutation {
createUsers(input:{
user_name: "${values.name}"
age: ${values.age}
sex: "${values.sex}"
weight: ${values.weight}
smoking:"${values.smoking}"
drinking: "${values.drinking}"
nationality:"${values.nationality}"
birth_type: "${values.birth_type}"
}
){
users{
user_name
}
}
}
`
});
postData(query)
}
})
return (
<div className="App">
<form onSubmit={formik.handleSubmit}>
<div className='input-container'>
<input
id="name"
name="name"
type="text"
placeholder="Name"
onChange={formik.handleChange}
value = {formik.values.name}
/>
<input
id="sex"
name="sex"
type="text"
placeholder="Sex"
onChange={formik.handleChange}
value = {formik.values.sex}
/>
<input
id="age"
name="age"
type="text"
placeholder="Age"
onChange={formik.handleChange}
value = {formik.values.age}
/>
<input
id="weight"
name="weight"
type="text"
placeholder="weight"
onChange={formik.handleChange}
value = {formik.values.weight}
/>
<input
id="smoking"
name="smoking"
type="text"
placeholder="smoking"
onChange={formik.handleChange}
value = {formik.values.smoking}
/>
<input
id="nationality"
name="nationality"
type="text"
placeholder="nationality"
onChange={formik.handleChange}
value = {formik.values.nationality}
/>
<input
id="birth_type"
name="birth_type"
type="text"
placeholder="birth_type"
onChange={formik.handleChange}
value = {formik.values.birth_type}
/>
</div>
<button type="submit">Submit</button>
</form>
</div>
);
}
export default App;

Formik breaks page layout

I have this code:
import React from "react";
import { useFormik } from 'formik';
const Registration = () => {
const formik = useFormik({
initialValues: {
email: '',
phone: '',
password: ''
}
})
return (
<div className="registration-page">
<form autoComplete="off">
<label htmlFor="email">Email</label>
<input value={formik.values.email}
id="email" type="email" placeholder="Enter your email"
/>
<label htmlFor="phone">Phone</label>
<input value={formik.values.phone}
id="phone" type="phone" placeholder="Enter your phone"
/>
<label htmlFor="email">Password</label>
<input value={formik.values.password}
id="password" type="password" placeholder="Enter your password"
/>
</form>
</div>
)
}
export default Registration;
The const formik part break the page with the message below:
Uncaught TypeError: Cannot read property 'useRef' of null
What can cause this? Remove the formik constant makes the page working fine.

Appending React form data to local CSV

I'm new to react and only have an entry level understanding of coding but need to use it for a project.
I've made a React form using Formik with four simple inputs that are logged as JSON strings when submitted. I would like to be able to send this data to a local CSV but I'm unsure about how to proceed from here. Any pointers would be greatly appreciated.
The code for my form is this:
import React from 'react';
import { Formik } from 'formik';
import { useFormik } from 'formik';
const SignupForm = () => {
const formik = useFormik({
initialValues: {
Username: '',
Address: '',
Postcode: '',
Details: '',
Score: '',
},
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="Username">Username</label>
<input
id="Username"
name="Username"
type="text"
onChange={formik.handleChange}
value={formik.values.Username}
/>
<label htmlFor="Address">Address</label>
<input
id="Address"
name="Address"
type="textarea"
onChange={formik.handleChange}
value={formik.values.Address}
/>
<label htmlFor="Postcode">Postcode</label>
<input
id="Postcode"
name="Postcode"
type="text"
onChange={formik.handleChange}
value={formik.values.Postcode}
/>
<label htmlFor="Details">Details</label>
<input
id="Details"
name="Details"
type="textarea"
onChange={formik.handleChange}
value={formik.values.Details}
/>
<label htmlFor="Score">Score</label>
<input
id="Score"
name="Score"
type="text"
onChange={formik.handleChange}
value={formik.values.Score}
/>
<button type="submit">Submit</button>
</form>
);
};
export default SignupForm;

React onSubmit placement

I have looked at multiple sources for using onSubmit functions in React and they always place onSubmit triggers as a Form attribute, like this
import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { register } from "../../../actions/auth/auth.action";
import { Container } from "react-bootstrap";
import {
Button,
Form,
Label,
Input,
} from "reactstrap";
class Register extends Component {
state = {
fname: "",
lname: "",
email: "",
password: ""
};
static propTypes = {
register: PropTypes.func.isRequired
};
handleChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
handleSubmit = e => {
e.preventDefault();
const { fname, lname, email, password } = this.state;
const newUser = {
name: {
first: fname,
last: lname
},
email: {
address: email
},
password
};
// Attempt to register user
this.props.register(newUser);
};
render() {
return(
<Form onSubmit={this.handleSubmit}>
<Label for="fname">First Name</Label>
<Input
type="text"
name="fname"
id="fname"
placeholder="Enter first name"
className="mb-3"
onChange={this.handleChange}
/>
<Label for="lname">Last Name</Label>
<Input
type="text"
name="lname"
id="lname"
placeholder="Enter last name"
className="mb-3"
onChange={this.handleChange}
/>
<Label for="email">Email</Label>
<Input
type="email"
name="email"
id="email"
placeholder="Enter email"
className="mb-3"
onChange={this.handleChange}
/>
<Label for="password">Password</Label>
<Input
type="password"
name="password"
id="password"
placeholder="Enter password"
className= "mb-3"
onChange={this.handleChange}
/>
<Button color="primary" style={{ marginTop: "2rem" }} block>
Register
</Button>
</Form>
);
};
};
const mapStateToProps = state => ({
error: state.error
});
export default connect(
mapStateToProps,
{ register }
)
(Register);
However, when I try this there is no way to call the function. (Ie. how does the button "know" when to call the onSubmit function when the call is a Form attrbute) I even tried added a type="submit" attribute to the button but that doesn't work either.
Just declare type="submit" in your button <button type="submit">send stuff</button> The type attribute is what onSubmit form is waiting for :) and remove e.preventDefault from your handleSubmit method and try again
The function will be called when submit event occurred.
Below code shows actions that trigger submit event.
class FormComponent extends React.Component {
handleSubmit = e => {
e.preventDefault();
console.log('submitted');
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="submit" /><br />
<button>Button with no attribute</button><br />
<button type="submit">submit typed Button</button><br />
<button type="button">button typed Button (no submit)</button><br />
<input type="text" value="Press enter to submit" />
</form>
);
}
}
ReactDOM.render(
<FormComponent />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

handleSubmit not getting called

I'm working on an app that uses strapi as the backenbd and react as the front
I'm using react hooks to build a login form. However my form submit does not call the submit handler
import React, { useState } from "react";
const Login = () => {
const [state, setState] = React.useState({ identifier: '', password: '' });
const handleChange = ({ target: { name, value } }) =>
setState(prevState => ({ ...prevState, [name]: value }));
const handleSubmit = async() => {
console.log('handleSubmit')
try {
const response = await fetch('./auth/local', { method: 'POST', body: state})
console.log(response)
} catch(err) {
console.log(err)
}
}
return (
<div>
<label htmlForm="identifier">identifier</label>
<input
id="identifier"
name="identifier"
onChange={handleChange}
value={state.identifier}
/>
<label htmlForm="password">password</label>
<input
id="password"
name="password"
onChange={handleChange}
value={state.password}
/>
<button onClick={() => handleSubmit}></button>
</div>
);
};
export default Login;
the handleSubmit function is never called.
You'd need to trigger the submit.
You can add a button to trigger a submit as shown below.
<div>
<form onSubmit={handleSubmit}>
<label htmlForm="identifier">identifier</label>
<input
id="identifier"
name="identifier"
onChange={handleChange}
value={state.identifier}
/>
<label htmlForm="password">password</label>
<input
id="password"
name="password"
onChange={handleChange}
value={state.password}
/>
👇
<button type="submit">Submit</button>
</form>
</div>
You can try it out out this Sandbox.
<div>
<label htmlForm="identifier">identifier</label>
<input
id="identifier"
name="identifier"
onChange={handleChange}
value={state.identifier}
/>
<label htmlForm="password">password</label>
<input
id="password"
name="password"
onChange={handleChange}
value={state.password}
/>
<button onClick={handleSubmit}></button>
</div>

Resources