formik how to trigger submit from outside - reactjs

I got a form like this
const SubtitleForm = ({ sub }) => {
const formik: any = useFormik({
initialValues: sub,
onSubmit: async (values) => {
const res = await update(values)
},
})
return (
<form className="subtitleFormComponent">
<input
className="subtitle"
autoComplete="off"
type="text"
name="name"
onChange={formik.handleChange}
value={formik.values.name}
/>
</form>
)
}
export default SubtitleForm
How can I trigger submit from outside this form / component ?

If you meant to have the submit button in a different component to the fields; I'd suggest to wrap both in the form. Then, you can use the useFormikContext in the inputs to update the data, and in the submit button.
A POC of the idea:
https://codesandbox.io/s/sharp-chebyshev-5nonm?file=/src/App.js

Related

how to handle multiple form input with dynamic dropdown render in react Js

I have created a form with multiple input there two dropdown first has option and second one's option changes dynamically based on selection of first dropdown. also i am storing all values in state with submit event.
Okay problem is i am either able to to get values and in state on submit event or either able to dynamically change the option for second dropdown.
But when I am trying to do both or trying to run two function on same onChange event its not trigging is any one can help me out why its not getting trigger and what is the issue.
link : if any one want to see code it dummy code
https://codesandbox.io/s/clever-mendel-ozt8tu?file=/src/App.js:0-1748
App.js
import "./styles.css";
import { useState } from "react";
function App() {
const data = {
first: ["car", "bus"],
second: ["bike", "train"],
third: ["plane", "rocket"]
};
const [option, setOption] = useState([]);
const getInput = (e) => {
let input = e.target.value;
setOption(data[input]);
};
const [values, setValues] = useState({
name: "",
city: "",
category: "",
ride: ""
});
const inputHandle = (e) => {
const { name, value } = e.target;
setValues({
...values,
[name]: value
});
};
const handleSubmit = (e) => {
e.preventDefault();
console.log(values);
};
return (
<>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="name"
name="name"
value={values.name}
onChange={inputHandle}
/>
<input
type="text"
placeholder="city"
name="city"
value={values.city}
onChange={inputHandle}
/>
<br />
<select
name="category"
values={values.category}
onChange={(e) => {
getInput();
inputHandle();
}}
>
<option defaultValue="category">category</option>
<option value="first">first</option>
<option value="second">Second</option>
<option value="third">Third</option>
</select>
<select name="ride" value={values.ride} onChange={inputHandle}>
{option.map((ele) => (
<option value={ele}>{ele}</option>
))}
</select>
<br />
<button type="submit">Submit</button>
</form>
</>
);
}
export default App;
For the handler of the onChange in the first select, you are taking in the event object e as parameter but not passing it forward in getInput() or inputHandle(). Therefore, you should write something like this:
onChange={(e) => {
getInput(e);
inputHandle(e);
}}
This should do the job. Also, try to use only one function in the handler, like the one you have used for submitting the form.
If you want to combine everything into one handler, you can use the following handler:
const categoryHandler = (event) => {
const selectName = event.target.name;
const selectValue = event.target.value;
setOption(data[selectValue]);
setValues({
...values,
selectName: selectValue
});
};

Get the values in the form, from a component outside the form

I've a component that is built using react-hook-form. I'm trying access the value in form, through a button that is sibling of the Form component. Basically the getvalue function should somehow get the values in the form.
Form.tsx
export default function Form({ onSubmit }) {
const { register, handleSubmit } = useForm({
defaultValues: {
firstName: "bill",
lastName: "luo",
email: "bluebill1049#hotmail.com"
}
});
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("firstName")} />
<input {...register("lastName")} />
<input {...register("email")} />
<button type="submit">Submit</button>
</form>
)
}
App.tsx
const onSubmit = data => console.log(data);
const getValue = ???
function App() {
return (
<Form onSubmit={onSubmit}/>
<button onClick={getValue} />
)
}
I want to get the form data values in getValue
You could use onChange to set the values in the form
<Form onSubmit={onSubmit} geValue={getValue}/>
and inside the Form.tsx
<form onSubmit={handleSubmit(onSubmit)} onChange={handleChange(getValue)}>
however i'm not really sure if this would work for you - can you elaborate more about what you are trying to do, maybe we can help you better.
Also, you should only pass callbacks to onSubmit and onChange so probably this is the correct syntax for that
<form onSubmit={(e) => handleSubmit(e, onSubmit)} onChange={(e) => handleChange(e, getValue)}>

Is there a way to set the initialValues using state with formik?

I am trying to set the initialvaluse in formik using values set in state with react hooks. I have the following below but it seems to not update , I have tried using enableReinitialize but that did not work. How can I set the initial values so that they are correct.
<Formik
initialValues={ initialValues}
I usually using formik with useFormik() hook.
When i want to add initial values it should go like this.
const SomePage = () => {
const [someName, setName] = React.useState('Somebody');
const formik = useFormik({
initialValues: {
name: someName
}
validationSchema: Yup.object(), // validation here
onSubmit: (values) => {
}
})
return (
<>
<form onSubmit={formik.handleSubmit}>
<input type="text" name="name" onChange={formik.handleChange} values={formik.values.name} />
</form>
</>
);
}

Submitting a Formik Form on Unmount

Is it possible to submit a Formik Form without having a submit button?
For example submitting the Form when the component unmounts so the user doesn't need to click a button to save.
Think of something like that:
import React from "react";
import { Formik, Form, Field } from "formik";
const Example = () => {
useEffect(() => {
return () => {
//trigger Submit or send Request with Form Values from here
};
}, []);
return (
<Formik
initialValues={{
firstName: "",
lastName: "",
}}
onSubmit={(values, { setSubmitting }) => {
//send Request
}}
>
{() => (
<Form>
<Field name="firstName" />
<Field name="lastName" />
</Form>
)}
</Formik>
);
};
export default Example;
You can create a functional component that auto-submits. By having it render inside the component, you have reference to the context of the form. You can use:
import { useFormikContext } from 'formik';
function AutoSubmitToken() {
// Grab values and submitForm from context
const { values, submitForm } = useFormikContext();
React.useEffect(() => {
return submitForm;
}, [submitForm]);
return null;
};
You can use it under the component as such
<Form>
<Field name="token" type="tel" />
<AutoSubmitToken />
</Form>
You can read all about it here

My Login page in React isn't giving the output that I want

I am new to React and Javascript and one of the exercises that I was doing is to create a Login Page. When I give the username and password I want them to be displayed in the console the following way:
{username: "username", password: "password"}
Instead I am getting the following output:
{p:"p", pa:"pa", pas:"pas", pass:"pass",..., password:"password" , u:"u", us:"us", use:"use"..., username:"username" }
I am following the tutorials but I am getting that result. Can somebody help me spotting my error?
import React, {useState} from 'react';
import {Button, TextField} from '#material-ui/core';
export default function Login(){
const [formState, setFormState] = useState({
values:{}
})
};
const handleChange = event => {
event.persist();
setFormState( formState => ({
...formState,
values:{
...formState.values,
[event.target.value]:event.target.value
}
}));
};
const handleSubmit = event =>{
event.preventDefault();
console.log(formState.values)
}
return (
<div>
<form className="form" onSubmit={handleSubmit}>
<TextField
label="Username"
name="username"
onChange={handleChange}
value=formState.values.username
></TextField>
<TextField
label="Password"
name="password"
onChange={handleChange}
value=formState.values.password
></TextField>
<Button type="submit">Login</Button>
</form>
</div>
);
Your handle change is using event.target.value as key. You need to use the input's name which identifies your input box instead.
Change your handleChange like this -
const handleChange = event => {
event.persist();
const values = { values: { ...formState.values, [event.target.name]:event.target.value}}; //name as key instead of value
setFormState(values);
};
What I would recommend is structuring your state like this - {username: "", password: ""};

Resources