# 表单

* 在 React 里，HTML 表单元素的工作方式和其他的 DOM 元素有些不同，这是因为表单元素通常会保持一些内部的 state
* 表单具有默认的 HTML 表单行为，即在用户提交表单后浏览到新页面，如果你在 React 中执行相同的代码，它依然有效，

  但大多数情况下，使用 JavaScript 函数可以很方便的处理表单的提交，同时还可以访问用户填写的表单数据，实现这种效果的标准方式是 受控组件

## 受控组件

> 在 HTML 中，表单元素（如 input、textarea、select）之类的表单元素通常自己维护 state，并根据用户输入的进行更新，而在 React 中， 可变状态 mutable state 通常保存在组件的 state 属性中，并且只能通过使用 setState() 更新
>
> 我们可以把两者结合起来，使 React 的 state 成为 **唯一数据源**。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作，被 React 以这种方式控制取值的表单输入元素就叫做 受控组件

* 设置了 value 属性，显示的值始终为 this.state.value，这使得 React 的 state 成为唯一数据源
* 设置了 onChange 属性，使得每次按键时都会执行并更新 React 的 state，因此显示的值将随着用户输入而更新
* input 和 select 一致

## select

```markup
<select>
  <option value="grapefruit">葡萄柚</option>
  <option value="lime">酸橙</option>
  <option selected value="coconut">椰子</option>
  <option value="mango">芒果</option>
</select>
```

* 由于 selected 属性的缘故，椰子选项默认被选中。React 并不会使用 selected 属性，而是在根 select 标签上使用 value 属性
* 你可以将数组传递到 value 属性中，以支持在 select 标签中选择多个选项
* 总的来说，这使得 input、textarea、select之类的标签都非常相似 它们都接受一个 value 属性，你可以使用它来实现受控组件

## 文件 input

* 允许用户从存储设备中选择一个或多个文件，将其上传到服务器，或通过使用 JavaScript 的 File API 进行控制
* 因为它的 value 只读，所以它是 React 中的一个 **非受控** 组件

## 处理多个输入

* 当需要处理多个 input 元素时，我们可以给每个元素添加 name 属性，并让处理函数根据 event.target.name 的值选择要执行的操作

  \`\`\`jsx harmony

class Reservation extends React.Component { constructor(props) { super(props); this.state = { isGoing: true, numberOfGuests: 2 };

```
this.handleInputChange = this.handleInputChange.bind(this);
```

}

handleInputChange(event) { const target = event.target; const value = target.name === 'isGoing' ? target.checked : target.value; const name = target.name;

```
this.setState({
  [name]: value
});
```

}

render() { return (  参与: \
&#x20;来宾人数:  ); } }

````
* 这里面使用了 ES6 计算属性名称的语法更新给定输入名称对应的 state 值
```javascript

// es6
this.setState({
    [name]: value
})

// es5
var partialState = {};
partialState[name] = value;
this.setState(partialState);
````

* 由于 setState() 自动将部分 state 合并到当前 state，只需要调用它更改部分 state 即可

## 受控输入空值

* 在受控组件上指定 value 的 prop 会阻止用户更改输入，如果你指定了 value，但输入仍可编辑，则可能是你意外地将 value 设置为 undefined 或 null
* 输入最初被锁定，但在短时间延迟后变为可编辑

## 受控组件的替代品

* 有时使用受控组件会很麻烦，因为你需要为数据变化的每种方式都编写事件处理函数，并通过一个 React 组件传递所有的输入 state。

## 成熟的解决方案

* Formik 是个不错的选择


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://zg-zhang.gitbook.io/note/react/offical-website/main-concepts/forms.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
