diff --git a/docs/note/React.md b/docs/note/React.md
index a647aef9..858a450f 100644
--- a/docs/note/React.md
+++ b/docs/note/React.md
@@ -144,7 +144,7 @@ root.render()
- 当数据发生变化,可以调用 `this.setState` 来更新数据,通知React执行视图更新
- update操作时,会重新调用render函数,使用最新的数据来渲染界面
-:::success
+::: tip
需要注意的是,在constructor中我们调用了`super`,因为App类是继承自React.Component类,调用`super`即调用了其父类的构造函数,让我们的App组件可以继承一些内置属性/方法如`state setState render`
:::
@@ -2487,6 +2487,8 @@ const CustomInput = forwardRef((props, ref) => {
在React中,HTML表单的处理方式和普通DOM元素不太一样:表单通常会保存在一些内部的state中,并且根据用户的输入进行更新
+下例中创建了一个非受控组件,React只能被动从组件接受值并更新到state中,而无法主动更新组件的值
+
```tsx
// Input.jsx
import React, { PureComponent } from 'react'
@@ -2517,11 +2519,426 @@ export default class Input extends PureComponent {
}
```
+我们对例子稍加改动,将组件的`value`属性设置为state中的值,从而实现受控组件。
+
+需要注意的是,绑定`value`属性的同时,我们也要绑定`onChange`事件,供用户输入时对state进行更新
+
+```tsx {8,22}
+// Input.jsx
+import React, { PureComponent } from 'react'
+
+export default class Input extends PureComponent {
+ constructor(props) {
+ super(props)
+ this.state = {
+ value: 'default Value'
+ }
+ }
+
+ handleInputChange = (ev) => {
+ this.setState({
+ value: ev.target.value
+ })
+ }
+
+ render() {
+ return (
+
+
currentValue: {this.state.value}
+
+
+ )
+ }
+}
+```
+
+this.state.value默认值 => 渲染到Input标签内 => 用户输入 => 触发onChange事件 => 更新state => 渲染到Input标签内 => ...
+
+React要求我们要么指定`onChange`要么指定`readOnly`,只绑定`value`属性时,控制台会抛出错误
+
+### 使用受控组件的几个例子
+
+下例中分别使用`input`创建了几个受控组件,文本框、单选、多选
+
+```tsx
+import React, { PureComponent } from 'react'
+
+export default class Form extends PureComponent {
+ constructor(props) {
+ super(props)
+ this.state = {
+ username: 'ziu',
+ password: '123456',
+ isAgree: false,
+ hobbies: [
+ { value: 'sing', label: 'Sing', isChecked: false },
+ { value: 'dance', label: 'Dance', isChecked: false },
+ { value: 'rap', label: 'Rap', isChecked: false },
+ { value: 'music', label: 'Music', isChecked: false }
+ ],
+ fruits: ['orange']
+ }
+ }
+
+ handleInputChange = (ev, idx) => {
+ this.setState({
+ [ev.target.name]: ev.target.value
+ })
+ }
+
+ handleAgreeChange = (ev) => {
+ this.setState({
+ isAgree: ev.target.checked
+ })
+ }
+
+ handleHobbyChange = (ev, idx) => {
+ const hobbies = [...this.state.hobbies] // IMPORTANT
+ hobbies[idx].isChecked = ev.target.checked
+ this.setState({
+ hobbies
+ })
+ }
+
+ handleSelectChange = (ev) => {
+ this.setState({
+ fruits: [...ev.target.selectedOptions].map((opt) => opt.value)
+ })
+ }
+
+ handleSubmitClick = () => {
+ const { username, password, isAgree, hobbies, fruits } = this.state
+ console.log(
+ username,
+ password,
+ isAgree,
+ hobbies.filter((h) => h.isChecked).map((h) => h.value),
+ fruits
+ )
+ }
+
+ render() {
+ const { username, password, isAgree, hobbies, fruits } = this.state
+ return (
+
+ )
+ }
+}
+```
+
+这里有一点小知识,关于可迭代对象,可以通过`Array.from`将可迭代对象转为数组
+
+方便我们使用数组的方法来操作选取的DOM列表
+
+简单做一下总结,如何在React中绑定受控组件:
+
+| Element | Value Property | Change Callback | New Value in Callback |
+| ------- | -------------- | --------------- | --------------------- |
+| `` | value | onChange | event.target.value |
+| `` | checked | onChange | event.target.checked |
+| `` | checked | onChange | event.target.checked |
+| `