原文地址:Controlled and uncontrolled form inputs in React don't have to be complicated
react的form受控和非受控话题
You may have seen many articles saying “you shouldn’t use setState
,”and the docs are claiming “ref
s are bad”… That is so contradictory. It’s hard to understand how to “get it right” and even what are the criteria for choosing.
(译:你可能已经看过很多文章说:“你不应该去使用 setState 去实现表单输入(setState是受控)”,并且官方文档声称:“使用 ref 的方式实现表单输入是不好的(ref是非受控)”。这些是互相矛盾的。这是很难去理解的,怎么样才能“得到正确的答案”,或者说选择标准是什么?)
How the hell are you supposed to make forms? (翻译:你到底应该怎么去实现form表单?)
After all, forms are central to many web apps out there. And yet, form handling in React seems to be a bit of a… corner stone?(翻译:毕竟,表单是许多网络应用程序的核心。然而,React中的表单处理似乎有点像一个墙角石)
Fear no more. Let me show you the differences between the approaches, as well as when you should use each.(翻译:不要担心,让我向你展示这些方法之间的差异,以及何时应该使用哪一种方法。)
The Uncontrolled(非受控)
Uncontrolled inputs are like traditional HTML form inputs:(翻译:非受控就像传统的HTML表单输入,如下:)
class Form extends Component {
render() {
return (
);
}
}
They remember what you typed. You can then get their value using a ref. For example, in onClick
handler of a button:(翻译:他们记得你输入的内容。然后,您可以使用ref获取其值。例如,在按钮的onClick处理程序中:)
class Form extends Component {
handleSubmitClick = () => {
const name = this._name.value;
// do something with `name`
}
render() {
return (
this._name = input} />
);
}
}
In other words, you have to ‘pull’ the value from the field when you need it. This can happen when the form is submitted.(翻译:换句话说,当你需要使用它时,你必须在这个字段所在的form中拉取这个值,即this._name = input绑定,this._name.value拉取)
That is the simplest way to implement the form inputs. There certainly are valid cases for using it, in simple forms in the real world; and when learning React.(翻译:这是实现表单输入的最简单方法。也是在你学习react时,现实世界中,最简单以及最有效的使用form表单的案例)
It’s not as powerful, though, so let’s see those controlled inputs next.(翻译:然而,它没有那么有效,让我们接下来看看那些受控输入)
The Controlled(受控)
A controlled input accepts its current value as a prop, as well as a callback to change that value. You could say it’s a more “React way” of approaching this (which doesn’t mean you should always use it).(翻译:一个受控输入由接受其当前值作为prop,以及改变该值的回调所组成。你可以说这是一种更接近“react思想”的方式。)
备注:但是这并不意味着你应该总是使用它
Which is fine and all… but the value of this input has to live in the state
somewhere. Typically, the component that renders the input (aka the form component) saves that in its state
:(翻译:这很好,但是这种输入的input值必须被存放在state中。通常,我们在使用表单组件时,是需要将其值保存在自身相关的state中,作者暗示还有其他保存方式)
class Form extends Component {
constructor() {
super();
this.state = {
name: '',
};
}
handleNameChange = (event) => {
this.setState({ name: event.target.value });
};
render() {
return (
);
}
}
(Of course, it can be in the state of another component, or even in the separate state store, like Redux.)(翻译:当然,它可以处于另一个组件的状态,甚至可以处于单独的状态存储中,例如:Redux)
Every time you type a new character, handleNameChange
is called. It takes in the new value of the input and sets it in the state.(翻译:每次键入新字符时,都会调用handleNameChange
。这个方法将会把输入的新值设置为相关的state状态。)
It starts out as an empty string —
''
.(翻译:以空内容开始)You type
a
andhandleNameChange
gets ana
and callssetState
. The input is then re-rendered to have the value ofa
.(翻译:键入a
时,handleNameChange
方法得到一个a
并调用setState
。然后重新呈现输入的值“a”。)You type
b
.handleNameChange
gets the value ofab
and sets that to the state. The input is re-rendered once more, now withvalue="ab"
.(翻译:你输入b
时,handleNameChange
获取ab
的值并将其设置为state。然后,输入再次重新渲染,现在值是“ab”。)
This flow kind of ‘pushes’ the value changes to the form component, so the Form
component always has the current value of the input, without needing to ask for it explicitly.(这种流将会把更改的值“推送”到表单组件,所以Form
组件总是具有输入的当前值,而不需要明确地要求它。)
This means your data (state) and UI (inputs) are always in sync. The state gives the value to the input, and the input asks the Form
to change the current value.(翻译:这意味着您的数据(状态)和UI(输入)始终保持同步。状态给输入赋值,输入通过Form
的改变当前值。)
This also means that the form component can respond to input changes immediately; for example, by:(翻译:这也意味着表单组件可以立即响应输入更改,例如可以实现如下内容:)
- in-place feedback, like validations(翻译:就地反馈,如验证)
- disabling the button unless all fields have valid data(翻译:除非所有字段都包含有效数据,否则禁用该按钮,应用与提交验证)
- enforcing a specific input format, like credit card numbers(翻译:强制执行特定的输入格式,如信用卡号)
But if you don’t need any of that and consider uncontrolled to be simpler, go for it.(翻译:但是,如果你没有这些需求,并考虑到非受控的简单性,想要使用非受控,那也是可以的。)
What makes an element “controlled”(怎么使元素“受控”)
There are other form elements, of course. You have checkboxes and radios and select
s and textareas.(翻译:当然还有其他形式的元素:复选框、单选框、下拉框和文本域。)
A form element becomes “controlled” if you set its value via a prop. That’s all.(翻译:如果通过prop设置其值,则表单元素将变为“受控”。就这样。)
Each of the form elements, though, has a different prop for setting that value, so here’s a little table to summarize:(翻译:但是,每个表单元素都有不同的用于设置该值的prop,这里有一个小表可以总结:)
Element | Value property | Change callback | New value in the callback |
---|---|---|---|
|
value="string" |
onChange |
event.target.value |
|
checked={boolean} |
onChange |
event.target.checked |
|
checked={boolean} |
onChange |
event.target.checked |
|
value="string" |
onChange |
event.target.value |
|
value="option value" |
onChange |
event.target.value |
Conclusion(结论)
Both the controlled and uncontrolled form fields have their merit. Evaluate your specific situation and pick the approach — what works for you is good enough.(翻译:受控和不受控制的form字段都有其优点。评估您的具体情况并选择方法 - 有用即是足够的。)
If your form is incredibly simple in terms of UI feedback, uncontrolled with refs is entirely fine. You don’t have to listen to what the various articles are saying is “bad.”(翻译:如果您的表单在UI反馈方面非常简单,那么非受控的参考完全没问题。
你不必听各种文章所说的“缺点”。)
feature | uncontrolled | controlled |
---|---|---|
one-time value retrieval (e.g. on submit) | ✅ | ✅ |
validating on submit | ✅ | ✅ |
instant field validation | ❌ | ✅ |
conditionally disabling submit button | ❌ | ✅ |
enforcing input format | ❌ | ✅ |
several inputs for one piece of data | ❌ | ✅ |
dynamic inputs | ❌ | ✅ |
Also, this is not an once-and-for-all decision: you can always migrate to controlled inputs. Going from uncontrolled to controlled inputs is not hard.(翻译:此外,这不是一劳永逸的决定:您始终可以迁移到受控输入。从非受控form转换到受控form并不难)
Finally, here’s the organized list of my posts about forms in React.(翻译:最后,放上关于React中表单有组织的帖子列表)
References(参考内容)
- Forms page on the official React docs
- Supported events
- Refs