Formik breaks page layout - reactjs

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.

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;

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

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"));

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;

Not able to see typed text in input using react hooks and controlled components

//The value coming from the input that triggered the event is getting updated in the state but not displaying in the browser, I don't really understand what's happening, I have been using the same method to update the state in my other project
import React, { useState } from "react";
const Register=()=>{
const [user,setUser]=useState({
name:"",
email:"",
password:"",
reenterPassword:""
});
let changeHandler=(e)=>{
const { name, value } = e.target
setUser({
...user,
[name]: value
})
}
return(
<div className="register">
<h1>Register</h1>
<input onChange={changeHandler} name="Username" placeholder="Please Enter Your Name" type="text" defaultValue="" value={user.name}/>
<input onChange={changeHandler} name="Email" placeholder="Enter your Email" type="email" value={user.email}/>
<input onChange={changeHandler} name="Password" placeholder="Create Your Password" type="password" value={user.password}/>
<input onChange={changeHandler} name="ReEnterPassword" placeholder="Re-Enter Your Password" type="password" value={user.reenterPassword}/>
<div className="button">Register</div>
<div>OR</div>
<div className="button">Login</div>
</div>
)
}
export default Register;
[1]: https://i.stack.imgur.com/G8beV.png
there is good answer here about it: https://stackoverflow.com/a/58877875/2091359
you should not use useState like this, you can do useState for each input separately like this:
const [name, setName] = useState('')
const handleChangeName = (e) => {
setName(e.target.value);
}
return(
<div className="register">
<h1>Register</h1>
<input onChange={handleChangeName} name="Username" placeholder="Please Enter Your Name" type="text" value={name}/>
...
or use useReduce
Try this code:
const Register=()=>{
const [user,setUser]=useState({
Username:"",
Email:"",
Password:"",
ReEnterPassword:""
});
let changeHandler=(e)=>{
const { name, value } = e.target
setUser({
...user,
[name]: value
})
}
return (
<div className="register">
<h1>Register</h1>
<input onChange={(e)=>changeHandler(e)} name="Username" placeholder="Please Enter Your Name" type="text" defaultValue="" value={user.name}/>
<input onChange={(e)=>changeHandler(e)} name="Email" placeholder="Enter your Email" type="email" value={user.email}/>
<input onChange={(e)=>changeHandler(e)} name="Password" placeholder="Create Your Password" type="password" value={user.password}/>
<input onChange={(e)=>changeHandler(e)} name="ReEnterPassword" placeholder="Re-Enter Your Password" type="password" value={user.reenterPassword}/>
<div className="button">Register</div>
<div>OR</div>
<div className="button">Login</div>
</div>
);
}
export default Register;
You need to use the same name for the html input attribute too, and try to use callback in the onChange event.

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>

Resources