I'm trying to use redux-form Field (together with Material-ui) and validation. It appears that the error messages are shown when I navigate away from the field (i.e. onBlur). What I would like to achieve is to do validation on the fly as the user types, and display error messages onChange event. How would I go about achieving this behavior?
import { TextField } from 'redux-form-material-ui';
import { Field, reduxForm } from 'redux-form';
const MyForm = (props) => (
<form>
<div className="form-group">
<Field
name="foo"
type="text"
hintText="Foo"
component={TextField}
/>
</form>
);
export default reduxForm({
form: 'MyForm',
validate
})(MyForm);
The default behaviour of validation is that messages are only displayed when fields are touched (i.e. onBlur).
I suppose you could work around that by using the touch method in componentWillMount, so that it becomes touched upon mount:
componentWillMount() {
const { touch } = this.props;
touch('foo');
}
That does however have the drawback of possibly showing any errors directly when the form is loaded, but in this case validation is triggered in onChange right away.
Have you played with the example in CodeSandbox? Like Dennis suggested, you could call "touch", though depending on your need you may choose to do this onChange:
<Field
name="username"
type="text"
component={renderField}
label="Username"
onChange={() => touch('username')}
/>
Related
import React from "react";
import { Field, Form } from "react-final-form";
export function LogInDialog(props: { open: boolean; onClose: () => void }) {
const onSubmit = vals => {
alert(JSON.stringify(vals));
};
console.log("logindialog");
return (
<Form
key="unique_key_0"
onSubmit={onSubmit}
render={({ handleSubmit, form, submitting, pristine, values }) => (
<form onSubmit={handleSubmit} key="unique_key_1" id="unique_id_1">
<Field
key="unique_key_2"
id="unique_id_2"
name="email"
component={({ input: { onChange, value }, label }) => (
<input
key="unique_key_3"
id="unique_id_3"
type="text"
value={value}
onChange={onChange}
/>
)}
></Field>
</form>
)}
/>
);
}
The input is losing its focus after every keystroke. In devtools, I can see the HTML form is created anew every time (it flashes pink). The React component itself however goes through rendering only once.
There are similar questions, however all of them suggest using unique keys. Such a solution doesn't seem to be working here.
Why is the input losing its focus over and over again? How do I fix it?
https://codesandbox.io/s/busy-torvalds-91zln
Since an inline lambda is used for the component, its identity changes every render.
While according to many other questions an unique key should be enough, moving the component function outside the master component fixes it altogether.
My component is this..... I get the initial form values from props in an object and that I need to set it in redux form to further update it.
Point here is also that I have a three step redux form having one form name. Example is here
import React from 'react';
import { Field, reduxForm } from 'redux-form'
import validate from './validate'
import renderField from './renderField'
const WizardFormFirstPage = props => {
const { handleSubmit } = props;
return (
<form onSubmit={handleSubmit}>
<Field
name="title"
type="text"
component={renderField}
label="Title"
/>
<Field
name="subTitle"
type="text"
component={renderField}
label="Sub-Title"
/>
<Field
name="price"
type="number"
component={renderField}
label="Price"
/>
<Field
name="brandName"
type="text"
component={renderField}
label="Brand Name"
/>
<div>
<button type="submit" className="btn btn-primary">Next</button>
</div>
</form>
);
};
export default reduxForm({
form: 'wizard',
destroyOnUnmount: false,
forceUnregisterOnUnmount: true,
validate,
})(WizardFormFirstPage);
You may in the wrong track. Putting value into the store require a connection to the redux but it is usually not recommend to connect a presentational component to the store.
As a consequence, I guess you may like to leave your component as it is and pass all eventhandler from the container to it.
Meanwhile, add a connection to the store for your container component, and push to the store in the callback of the ajax will do.
If you wish to access form values from redux-form from different components, you should probably use getFormValues selector and specify the form name as params. Pass the form name through props from the parent container to the stateless component. You can then access the form values from the props under the "formValues" field.
const mapStateToProps = (state, props) => ({
formValues: getFormValues(props.form)(state),
initialValues: props.initialValues,
});
I am using react-kendo-ui. I want to wrap Input from #progress/kendo-react-inputs to use it with ReduxForm. Please find my code below:
import React from 'react'
import { Input } from '#progress/kendo-react-inputs';
const InputText = ({ input, label, type, meta: { touched, error } }) => (
<div>
<label>{label}</label>
<div>
<Input {...input} type={type} placeholder={label} />
{touched && error && <span>{error}</span>}
</div>
</div>
)
export default InputText
Call the InputText from another component as below:
import React from 'react';
import { Field, reduxForm } from 'redux-form';
import { Input } from '#progress/kendo-react-inputs';
import InputText from './input-text';
const validateNotEmpty = value => !value ? 'Must enter a value' : null;
const onSubmit = (values) => {
console.log(values);
}
const AddLoc= ({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<div>
<Field
label="Address"
name="address"
component={InputText}
validate={validateNotEmpty}
/>
</div>
<button type="submit">Submit</button>
</form>
)
export default reduxForm({
form: 'AddLoc'
})(AddLoc)
But while typing inside the input text it keeps giving the following error/warning:
Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property `nativeEvent` on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist().
While typing inside the input text automatically outputs [object Object]. Please check the image above. Could anyone please let me know what is causing the error.
Thanks
The reduxForm works only with pure DOM <input />. Internally it clones the elements search the children and then attaches the onChange dynamically. So it will not work with the Input and the NumericTextBox from the #progress/kendo-react-inputs package. This statement is based on the official kendo documentation about integrating with the redux-form.
The same author of the redux-form have fork of it called react-final-form which could be used on any component that have Value and onChange props. By our tests it works with the components from #progress/kendo-react-inputs and #progress/kendo-react-dropdowns packages. It looks kendo already have an example using final-form in their integration section.
I was just playing a bit with a more generic way of dealing with form data, and figured that setting a single onChange listener on the wrapping form tag should work for all changes to input fields.
And indeed, it does - no surprise there. Events get called, I know what changed by inspecting event.target.name and can update state accordingly. Fully as expected.
However, React doesn't seem to like it and spams the well known "You provided a value prop to a form field without an onChange handler" console warning.
Would there be any other reason for not doing this, apart from the console warning? It seems to eliminate a lot of duplication React otherwise gets criticised about.
class App extends Component {
state = {
name: 'Default Name',
number: 12,
}
handleChange = (event) => {
this.setState({
[event.target.name]: event.target.value,
})
}
render() {
const { crashLogo } = this.props;
return (
<div className="App">
<form onChange={this.handleChange}>
<input type="text" name="name" value={this.state.name} />
<input type="number" name="number" value={this.state.number} />
</form>
</div>
);
}
}
Just for clarity: I'm not asking for alternative solutions, I know I can set the same change listener directly on every input, use redux-form, own wrapper components with context magic and so on...
I am trying to access the touched property on my redux form, but for some reason when I print the field props I only the value instead of the object. What am I missing?
import { reduxForm, Field } from 'redux-form';
render() {
const { fields: { email, phone }, handleSubmit } = this.props;
console.log(email) //prints just the value "email" instead of the field object with the touched method, etc. When I do console.log(email.touched) I get undefined error.
return (
<form onSubmit={handleSubmit(this.onSubmit)}>
<Field name="email" component="input" type="email" { ...email } />
<Field name="phone" component="input" type="number" { ...phone } />
</form>
);
}
export default ReduxFormTest = reduxForm({
form: 'uniqueForm',
fields: ['email', 'phone']
})(TestClass);
There were breaking changes in redux-forms from v5 to v6. Previously you could do something similar to what you have to access the touched field. If you want to do something similar to see if there are errors on a field, you need to create your own component to pass to redux-form's Field component.
Your custom component
const CustomComponent = function(field) {
return (
<div>
<input
type={field.type}
{...field.input}
/>
{field.meta.touched && field.meta.error && <div className='error'>{field.meta.error}</div>}
</div>
)
}
Then using it with the Field component
<Field name="my-prop" component={CustomComponent} />
Also take a look at the migration guide, hope this helps!
You are confusing v5 syntax with v6 syntax. In v6, your decorated form component is no longer passed this.props.fields. Re-read the migration guide, like #tyler-iguchi said.