controlled and uncontrolled components
React
the concept of controlled and uncontrolled components is relative to the form. In React
, the form element usually holds the internal state
, so it works differently from other HTML
elements. The different implementation of state
within the form element results in controlled and uncontrolled components.
controlled components
in the HTML
form elements, they usually maintain a set of state
and update UI
as the user inputs. This behavior is not controlled by our program. If we establish a dependency between the state
attribute and the value of the form element in React
, then update the state
attribute through the onChange
event and setState ()
. You can control what happens to the form during user input. React
form input elements that control values in this way are called controlled components. & nbsp;
if a input
input box is defined in React
, it does not have the same bi-directional binding function as v-model
in Vue
, that is to say, we do not have an instruction to combine the data with the input box, and the user enters the content in the input box, and then the data is updated synchronously.
class Input extends React.Component {
render () {
return <input name="username" />
}
}
when users enter content in the input box on the interface, it maintains a state
. This state
is not the this.state
that we usually see, but the abstract state
on each form element, so that we can update the UI
according to the user's input. If we want to control the content of the input box, the content of the input box depends on the value
attribute in input
. Then we can define an attribute named username
in this.state
, and specify value
on input
as this attribute.
class Input extends React.Component {
constructor (props) {
super(props);
this.state = { username: "1" };
}
render () {
return <input name="username" value={this.state.username} />
}
}
but at this time you will find that the content of input
is read-only, because value
will be controlled by our this.state.username
, and this.state.username
will not be updated automatically when users enter new content, so the content in input
will not change, and the console will usually throw a Warning
.
Warning: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.
you have provided a value
property for the form field without a onChange
handler, which will render the read-only field. If the field should be mutable, use defaultValue
, otherwise set onChange
or readOnly
. & nbsp;
this Warning
actually gives a solution to this problem. We only need to listen to the component's onChange
event to listen for changes in input and use setState
to update this.state.username
, so that we can control the value of this form element in the current component, which is the controlled component.
class Input extends React.Component {
constructor (props) {
super(props);
this.state = { username: "1" };
}
render () {
return (
<>
<input name="username" value={this.state.username}
onChange={e => this.setState({username: e.target.value})}
/>
<button onClick={() => console.log(this.state.username)} >Log</button>
</>
)
}
}
In addition, it should be noted that there are drawbacks if this component is called as a common component. Although the Input
component itself is a controlled component, the opposite caller loses control over changing the value of the Input
component, so for the caller, the Input
component is an uncontrolled component, and invoking the controlled component in the way uncontrolled components are used is an antipattern. The following examples belong to Hooks
.
// component provider
function Input({ defaultValue }) {
const [value, setValue] = React.useState(defaultValue)
return <input value={value} onChange={e => setValue(e.target.value)} />
}
// caller
function UseInput() {
return <Input defaultValue={1} />
}
if you want Input
components to be controlled for both the provider and the caller, you only need the provider to relinquish control.
// component provider
function Input({ value, onChange }) {
return <input value={value} onChange={onChange} />
}
// caller
function UseInput() {
const [value, setValue] = React.useState(1);
return <Input value={value} onChange={e => setValue(e.target.value)} />
}
uncontrolled components
if the form element does not go through state
, but is modified by ref
or directly manipulated DOM
, then its data cannot be controlled through state
, which is an uncontrolled component.
class Input extends React.Component {
constructor (props) {
super(props);
this.input = React.createRef();
}
render () {
return (
<>
<input name="username" ref={this.input} />
<button onClick={() => console.log(this.input.current.value)} >Log</button>
</>
)
}
}
Summary
controlled components
-
whenever the state of the form changes, it is written to the
state
of the component. -
in a controlled component, the state rendered by the component corresponds to its
value
orchecked prop
. -
react
flow ofstate
updates for controlled components:
& nbsp; & nbsp; * by setting the default value of the form in the initial state
.
& nbsp; & nbsp; * calls the onChange
event handler whenever the value of the form changes.
The
& nbsp; & nbsp; * event handler gets the changed state through the composite object event
, and updates the state
of the application.
& nbsp; & nbsp; * SetState
triggers the re-rendering of the view and completes the update of the form component values.
uncontrolled components
-
if a form component does not have
value prop
, it can be called an uncontrolled component. -
an uncontrolled component is an antipattern whose value is not controlled by the component's own
state
orprops
. -
usually needs to add
ref prop
to access the underlyingDOM
element after rendering. -
you can specify the
value
value by addingdefaultValue
.