[译]不要把React中的受控和非受控的form表单输入搞复杂

原文地址:Controlled and uncontrolled form inputs in React don't have to be complicated
react的form受控和非受控话题

不要把React中的受控和非受控的form表单输入搞复杂

You may have seen many articles saying “you shouldn’t use setState,”and the docs are claiming refs 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 (
      <div>
        <input type="text" />
      </div>
    );
  }
}

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 (
      <div>
        <input type="text" ref={input => this._name = input} />
        <button onClick={this.handleSubmitClick}>Sign up</button>
      </div>
    );
  }
}

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思想”的方式。)

备注:但是这并不意味着你应该总是使用它

<input value={someValue} onChange={handleChange} />

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 (
      <div>
        <input
          type="text"
          value={this.state.name}
          onChange={this.handleNameChange}
        />
      </div>
    );
  }
}

(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状态。)

image
  • It starts out as an empty string — ''.(翻译:以空内容开始)

  • You type a and handleNameChange gets an a and calls setState. The input is then re-rendered to have the value of a.(翻译:键入a时,handleNameChange方法得到一个a并调用setState。然后重新呈现输入的值“a”。)

  • You type b. handleNameChange gets the value of ab and sets that to the state. The input is re-rendered once more, now with value="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 selects 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
<input type="text" /> value="string" onChange event.target.value
<input type="checkbox" /> checked={boolean} onChange event.target.checked
<input type="radio" /> checked={boolean} onChange event.target.checked
<textarea /> value="string" onChange event.target.value
<select /> 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(参考内容)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,098评论 0 10
  • ——2012年12月美卡人物 生命的意义不仅限于生存 他拍戏出于偶然,在大一那年,机缘巧合认识了唐人公司投拍的电...
    hugh_diary阅读 395评论 0 1
  • 天辰低着头,把已经熟睡的绵儿轻轻地放在地上。一丝微笑挂在他的嘴角,是那么温暖,充满了爱恋。泪水肆意地在他刚毅的面庞...
    路小札阅读 954评论 0 3
  • 大雪是也阅读 189评论 0 0