- First, there is the React component in the form
- The controlled components
- Uncontrolled component
function MyForm() {
const [value, setValue] = useState(' ')
const handleChange = (evt) = > {
setValue(evt.target.value)
}
return <input value={value} onChange={this.handleChange} />
}
Copy the code
Controlled components. The state of a form component is fully controlled by React, but frequent updates to the state can cause performance problems
function MyForm() {
const inputRef = useRef()
const handleSubmit = (evt) = > {
// Use prevetnDefault to prevent pages from being refreshed
evt.preventDefault()
alert(inputRef.current.value)
}
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input ref={inputRef} />
</label>
<input type="submit" value="Submit" />
</form>)}Copy the code
Uncontrolled components, where the value of a form element is not determined by the parent component, but is a completely internal state.
As you can see, the input process has no effect on the overall state of the component, and does not result in a re-rendering of the component.
Simplify form processing with Hooks
Previously, for controlled components, follow these two steps:
- Set a State to bind to the value of the form element
- Listen for the onChange event of the form element to synchronize the form value to State
That is, maintaining the state logic of a form component has three core parts:
- Field name
- Binding the value value
- Handle the onChange event
Since the logic is the same for each form element, we can reuse the logic using hooks
- Use hooks to maintain the entire form. Use root names to set values or modify them
Basic implementation:
const useForm = (initialValues = {}) = > {
// Set the status of the entire form to values
const [values, setValues] = useState(initialValues)
const setFieldValue = useCallback((name,value) = > {
setValues((value) = > return {
...values,
[name]: value
})
}, [])
return { values, setFieldValue }
}
Copy the code
When using:
// ...
const [values, setFieldValues] = useForm()
// ...
<input value={values.name || null} onChange={setFieldValues('name',evt.target.value)} />
<input value={values.email || null} onChange={setFieldValues('email', evt.target.value)} / >
Copy the code
Most open source forms solutions are based on a core principle: separate form state management into a reusable Hook.
- Handling form validation
- Add one more essential logic for form processing: form validation
Follow the same state-driven principle:
- First: How do you define such an error state
- Second: how to set the error state
Add the API interface to the existing useForm Hook:
// Provide a validators object that provides validation functions for a field
const useForm = (initialValues = {}, validators) = > {
const [values,setValues] = useState(initialValues)
// Defines the errors state
const [errors, setErrors] = useState({})
const setFieldValue = useCallback((name, value) = >{ setValues(({ ... values, [name]: value }))// Call a validation function to validate user input
if (validators[name]) {
const errMsg = validators[name](value)
setErrors((errors) = > ({
...errors,
[name]: errMsg || null
}))
}
},[validators])
return { values, errors, setFieldValue }
}
Copy the code