Formik ErrorMessage not displaying for the first time - reactjs

I am using Formik forms in react project. I have the following code inside <Formik><Form>
<Field name="zip" validate={some validation is here}>
<input {...fieldProps.field}
id="zip"
name="zip"
className="form-control"
placeholder="zip"
required={true}
maxLength={5}
onKeyDown={(event) => this.onZipChange(event)}/>
</Field>
<ErrorMessage name="zip" render={msg => <div>{msg}</div>} />
When form is rendered, I make changes to the input, for example, remove one number from zip, so in props.formProps.errors errors` texts appear, but ErrorMessage is not displaying. After I click to any places of the page it appears, and then it continue working as expected: on key down it display ErrorMessage if any errors in zip, and hide if zip is valid.
The problem is only for the first time when form is rendered.
Any ideas, what can cause the issue?

This is expected behavior. <ErrorMessage /> is only displayed when both of the following conditions are fulfilled:
There is an error message for the given field
That field's touched property is true
By default, Formik will set touched to true on blur. So this is why the error message only displays when you click outside the input.
If you want to force the error message to appear even before the blur, you may manually set the input's touched property to true. This may be done multiple ways but the simplest is via initialTouched prop on <Formik />. If the form comes preloaded with data from the backend, you may also want to set validateOnMount prop to true.
For example:
<Formik
validateOnMount
initialTouched={{zip: true}}
>
...
</Formik>

Related

How do I update a react-final-forms internal state to what my apps state is?

I'm aware of FormSpy to update based on subscriptions to the form's changed input values.
I'm just not 100% sure on implementation for it. I also tried mutations but that didn't update the state values.
<Field name="city">
{({ input, meta }) => (
<label
>
City
</label>
<input
{...input}
type="text"
placeholder="123 Main Street"
id="city"
onChange={(e) => updatedLocationValues(e)}
value={location.city}
/>
)}
</Field>
This field is tied to state and is auto-populated by another field (users can still change it if they want through manual inputs)
The onChange is updating the state.
However React-final-form doesn't know about this state change. This is where FormSpy is supposed to come in but i'm not sure how to integrate it here.

React-hook-form with Material-ui textfield without autoFocus defaultValue disappeared during form submit

I have problem using react-hook-form v7 + material-ui textfield. The defaultValue working if I set autoFocus or I manually change the textfield value. However if I just submit without mouse click on the filed that not autoFocus, the defaultValue disappeared during the form submit. Please check codesandbox link
Test 1: don't touch anything, click submit, you will see submit value only has title but missing name and desc
Test 2: mouse click or change value in name, you will see after submit the value of name is there
My question is how to make this default value always submit even though without mouse click or change the value of the textField?
Please help and thanks in advance
To use Material-ui with react-hook-form. It is better to wrap it with Controller to allow react-hook-form to link with the 3rd party library element.
https://react-hook-form.com/api/usecontroller/controller
Wrap Textfield with Controller
const { handleSubmit, control } = useForm();
...
<Controller
render={({ field }) => (
<TextField
autoFocus
margin="dense"
id="title"
label="Title"
type="text"
fullWidth
{...field}
/>
)}
control={control}
name="title"
defaultValue={data.title}
/>
...
After that, the default value will be able to work as expected.
Here is the codesandbox for demo.

Error in Material UI DatePicker does not invalidate the Field/Form

The DatePicker is in a wrapper component and although the error message is displaying correctly but it isn't invalidate the field or form if the date is set as incorrect. I know about the onError callback function but I don't know what to call here. The validation is not occuring on onSubmit hence can't use the SubmissionError or submitfailed.
I can pass an external validator from form field but I just leave it as a last option.
Date Picker
<InlineDatePicker
format={DATE_FORMAT_UI}
keyboard
mask={mask}
maxDate={maxDate}
minDate={minDate}
placeholder={DATE_FORMAT_UI}
value={formattedStoreValue}
variant="outlined"
onBlur={this.handleBlur}
onChange={this.handleChange}
**onError={(_,error)=>{ don't know what to do here })}**
{...other}
/>
Form Field
<Field
name={someDate}
component={InlineDatePickerField}
**validate={[required]} //If not possible then add another validator here as last option**
id={someDate}
label="To"
minDate={this.minDate()}
required
className="w-full"
/>

Checkbox doesn't toggle when rendered from a function

This is a little bizarre of a problem and I haven't been able to track down the issue. I have a checkbox / input combo I created using Semantic-UI React (Form.Checkbox). The checkbox portion is added to the input, think addon, for a little combo input situation. Desired behavior is when the checkbox is checked it allows the user to type input into the input portion of the combo input. The checkbox's state is managed in the component's local state.
If I just include this code:
<Form.Field className="field">
<label>{field.label}</label>
<Input
{...field.input}
label={{ basic: true, content: <Checkbox
onChange={() => this.setState({sendEmail: !this.state.sendEmail})}
checked={this.state.sendEmail} />,
style: {'borderRight': '0px'}
}}
disabled={!this.state.sendEmail}
labelPosition='left'
placeholder='Email Address'
/>
</Form.Field>
in the jsx (render function) for the component, the toggling actually happens, state is managed properly etc. But when I put the same code into a function to render back the same input like so:
renderCheckboxInputField(field){
return(
<div>
<Form.Field className="field">
<label>{field.label}</label>
<Input
{...field.input}
label={{ basic: true, content: <Checkbox
onChange={() => this.setState({sendEmail: !this.state.sendEmail})}
checked={this.state.sendEmail} />,
style: {'borderRight': '0px'}
}}
disabled={!this.state.sendEmail}
labelPosition='left'
placeholder='Email Address'
/>
</Form.Field>
</div>
);
}
and call it from here:
<Grid.Column>
<Field
name="email"
label="Send Email"
component={this.renderCheckboxInputField}
/>
</Grid.Column>
the checkbox doesn't actually visually toggle, though the state is being updated properly. You might ask why not just keep it in the first location where it already works, but a) for reusability I placed it within the function, and b) I wanted to include it this way inside of the <Field /> component at the bottom because I am using Redux Form for validation on the input portion of the checkbox / input combo I made.
So for some clarification the <Field /> component comes from Redux Form. The <Form.Field /> pertains to a Semantic-UI React component. And all of the hacky stuff inside of the <Input /> component's label field is me just customizing the input to look as I desire.
You are calling this.renderCheckboxInputField without any params, but in function definition you pass 'field' and using it inside

How to grab Textfield input values with Redux-form using MaterialUI

Goal: Get the input values from a material UI component and pass them to an action creator in a handleSubmit function.
<Field name='email'
component={email =>
<TextField
fullWidth
autoComplete='off'
className={classes.textField}
id='email-text-field'
label='Email'
value={email} />
} />
<Field name='password'
component={password =>
<TextField
type='password'
fullWidth
autoComplete='off'
className={classes.textField}
id='password-text-field'
label='Password'
value={password} />
} />
This is how it is being connected to Redux:
#reduxForm({form: 'loginForm', fields: ['email', 'password']})
The warnings I'm getting in my chrome dev tools console is:
Failed prop type: Invalid prop value supplied to TextField.
Warning: Failed prop type: Invalid prop value supplied to Input.`
Additionally, the email field in my login form shows [Object, object}
My guess is that this is happening due to the fact that props are being passed from the
Any ideas on where I've gone wrong?
When you want to use a custom field for Redux-Form, Redux-form gives you access to both props like onChange etc, but also other meta-data (like if the form has been touched or not). These different kinds of props are grouped depending on type.
The interesting part for you is that all the attributes associated with a normal input element (like onChange, value, type) are grouped in props.input. So the argument you call password is actually the whole props object that is sent down to the component. It looks something like this {input:{ value: 'someValue', onChange: somFunction.. etc. etc}, meta: { touched: false, etc. etc.}}.
That means that if you want to use the TextField like you do now, you need to do something like:
<Field name='email'
component={({input}) =>
<TextField
value={input.value}
onChange={input.onChange}
fullWidth
autoComplete='off'
className={classes.textField}
id='email-text-field'
label='Email'
/>
} />
This can get pretty messy, especially if you want to use the meta props, so it's often worth it to break the custom component logic out into its own function, like they do in the example in the docs: https://redux-form.com/7.0.4/examples/material-ui/
You may also be interested to know that for material-ui components, there actually already exists a library that has done most of that manual work for you: redux-form-material-ui.

Resources