React final form triggers handleSubmit after the initial render - reactjs

I've got only Switch component in my react-final-form. It looks like this:
<Form
onSubmit={onSubmit}
initialValues={initialValues}
render={({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<Field name="booleanValue" component={Switch} onChange={handleSubmit}/> //triggers when receives value
</form>
)
}
/>
I want to trigger handleSubmit only after user changes, not at first render of the form.

<Field/> doesn't have an onChange prop like you are attempting. Something like this could work.
import { OnChange } from 'react-final-form-listeners'
...
<Form
onSubmit={onSubmit}
initialValues={initialValues}
render={({ handleSubmit, form }) => (
<form onSubmit={handleSubmit}>
<Field name="booleanValue" component={Switch}/>
<OnChange name="booleanValue">
{(value, previousValue) => {
form.submit()
}}
</OnChange>
</form>
)
}
/>
P.S. I hope your Switch component knows to get its value and onChange from the input prop.
Hope that helps!

Related

How to fix Type Props Error when onChange Event in Formik/Field Input

When I want to trigger the onChange event of Formik/Field(input).
I don't know how to trigger the onChange Event in Formik/Field. So I tried to trigger onChange event in Formik/Form and get the id of event params. But it is facing the problem of Props in Typescript.
Please check my code snippet and let me know how to fix this problem. Thanks in advance.
const InputCustomerForm = () => {
...
const handleFormChange = (event: FormEvent) => {
if (event.target.id === "mobileNumber"){
const value = phoneConvertor(event.target.value);
setUpdatedPhoneNumber(value);
}
}
return (
<OrderPaymentFormContainer className={`${showAccount === true ? 'show' : 'hidden'}`}>
<Formik
initialValues={initialValues}
enableReinitialize={true}
validationSchema={OrderPaymentFormSchema}
onSubmit={(values, actions) => {
handleSendEmail(values);
actions.setSubmitting(false);
}}
>{
({ handleSubmit, errors, touched, isValid }) => (
<Form onSubmit={handleSubmit} onChange={handleFormChange}>
...
<div>
<label>
Mobile Phone Number
</label>
<div>
<div>
<Field id="countryCode" name="countryCode" as="select">
<option defaultValue="1">US</option>
</Field>
</div>
<div>
<Field id="mobileNumber" name="mobileNumber" placeholder="(201) 555-0123" value={updatedPhoneNumber}/>
</div>
</div>
{errors.mobileNumber && touched.mobileNumber ?
(<div className="order-detail--card-form-item-error">{errors.mobileNumber}</div>) : null
}
</div>
...
</Form>
)
}
</Formik>
</OrderPaymentFormContainer>
)
}
export default InputCustomerForm;
As we can see, I hope to get the changed value of input and want to do some function with changed values and return to Input's current value. But it's not working now. Please let me know the problem how to resolve this problem. Thanks
I tried it by manually using pure function but it's not working.
I hope to resolve this problem in typescript.

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)}>

How can i pass render props to children in React functional components?

i am using react-final-form I have a Form Component something like this:
export function Form = ({ children, onSubmit, initialValues, ...props }) => {
return (
<FinalForm
initialValues={initialValues}
onSubmit={onSubmit}
render={({ handleSubmit, submitting, pristine, valid }) => (
<form onSubmit={handleSubmit} className="space-y-6" {...props}>
{children}
</form>
)}
/>
)
}
export default Form;
I want to use this form component like this:
<Form>
({ valid, pristine, submitting } => (
<TextInput name="email" label="Email Address" type="email" />
<Button text="Login" disabled={!valid || pristine || submitting} />
)
</Form>
How can i pass the props valid, pristine and submitting to my childs so i can use it for e.g. disable a Button?
Instead of
{children}
Try this,
{
React.Children.map(children, child => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { submitting, pristine, valid });
}
return child;
});
}

react-hook -form with SliderComponent input

Im new to react and I am trying to use a SliderComponent in a react Hook form but I cant seem able to fully understand how Controller works.
Here is my SliderComponent using react-input-slider:
export default function SliderComponent(props) {
const { axis, xmax, xmin, xstep, onChange } = props;;
return (
<div>
<Slider
axis={axis}
x={value.x}
xmax={xmax}
xmin={xmin}
xstep={xstep}
onChange={onChange}
/>
</div>
);
}
And here is my form:
export default function BiometricForm() {
const { handleSubmit, control } = useForm();
return (
<div className="registerForm_Container">
<form onSubmit={handleSubmit(onsubmit)}>
<Controller
control={control}
name="test"
render={({ props: { x, axis, xmax, xmin, xstep } }) => (
<SliderComponent
axis={"x"}
xmax={100}
xmin={1}
xstep={1}
value={x}
onChange={(e) => x.onChange(parseInt(e.target.value))}
/>
)}
/>
<button className="registerForm_Container_button" type="submit">
Register
</button>
</form>
</div>
);
}
I think it might be something to do with useState and that I am not able to reach useState of component. I have read that maybe its not necessary , any help? Thank you!
You are absolutely right, if you use RHF you don't need useState because RHF handles the form state for you. The important thing here is to pass an onChange handler to your <SliderComponent />, so that RHF can watch for value changes of your <SliderComponent /> and update the form state. You should also provide a defaultValue for the field, if you don't want it to be undefined if the user doesn't change the slider before submitting.
Also without the useState inside <SliderComponent />, you can also omit the <SliderComponent /> and just use <Slider />.
function BiometricForm() {
const { handleSubmit, control } = useForm();
const onSubmit = (data) => console.log(data);
return (
<div className="registerForm_Container">
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
control={control}
name="test"
defaultValue={50}
render={({ field: { value, onChange } }) => (
<Slider
axis={"x"}
xmax={100}
xmin={1}
xstep={1}
onChange={({ x }) => onChange(x)}
x={value}
/>
)}
/>
<input type="submit" />
</form>
</div>
);
}

How to add a Clear Button on a Formik Textfield

I want to add a Clear Button as a convenience to users:
constructor(props) {
this.emailInput = React.createRef();
}
<Field label="Email" name="email" ref={this.emailInput} onChange={onChange} component={TextField}/>
But get this:
Warning: Function components cannot be given refs. Attempts to access this ref will fail.
To reset particular fields, use setFieldValue to set value to an empty string.
setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void
Set the value of a field imperatively. field should match the key of values you wish to update. Useful for creating custom input change handlers.
- Formik Documentation
Eg:
<Formik
initialValues={initialValues}
...
>
{({ setFieldValue }) =>
...
<button type="reset" onClick={() => setFieldValue('fieldName', '')}>
Reset This
</button>
...
To reset all fields, use resetForm.
resetForm: (nextValues?: Values) => void
Imperatively reset the form. This will clear errors and touched, set isSubmitting to false, isValidating to false, and rerun mapPropsToValues with the current WrappedComponent's props or what's passed as an argument.
- Formik Documentation
Eg:
<Formik
initialValues={initialValues}
...
>
{({ resetForm }) =>
...
<button type="reset" onClick={resetForm}>
Reset All
</button>
...
Codesandbox : https://codesandbox.io/s/7122xmovnq
Formik has a built in method called resetForm which can be accessed like the other formik methods. In your form you probably have something like
<Formik
initialValues={something}
validationSchem={someSchema}
render={() => {
...some form stuff
}
}
/>
you can access the formik props inside that render method and do what you want with them:
<Formik
initialValues={something}
validationSchem={someSchema}
render={(props) => {
...some form stuff
<button type="button" onClick={() => props.resetForm()}>reset form</button>
}
}
/>
you can try to set a reset button in your form, e.g
<form>
<Field label="Email" name="email" onChange={onChange} component={TextField}/>
<input type="reset" value="Reset">
</form>
I took the example here, it has to reset all of the inputs in the form

Resources