From bb73633973be94cf036f34033d8542602d279cbd Mon Sep 17 00:00:00 2001 From: asahi <496063163@qq.com> Date: Sun, 28 May 2023 20:58:00 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=85=E8=AF=BBreact=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react/react文档.md | 98 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/react/react文档.md b/react/react文档.md index ae48483..4b54345 100644 --- a/react/react文档.md +++ b/react/react文档.md @@ -275,7 +275,103 @@ function Item({ name, isPacked }) { return
  • {name}
  • ; } ``` - +## 组件的渲染和提交 +### 组件渲染的原因 +- 组件的初次渲染 +- 组件(或先祖组件)的状态发生了变化 +#### 初次渲染 +当引用启动时,会触发初次渲染 +#### 状态更新时重新渲染 +当初次渲染完成后,可以通过set函数来更新state并触发渲染。更新组件状态会将重新渲染加入到队列。 + +对于初次渲染,React会调用根部组件的方法来进行渲染,而对于状态更新触发的渲染,react只会调用状态更新对应组件的函数 +> 对于组件的渲染,其过程是递归的。如果待渲染的组件中包含了子组件,那么react会对子组件进行渲染,对子组件中包含的孙组件也同样。渲染会对组件子树中所有的组件进行渲染。 + +#### 渲染差异 +React只会在渲染之间存在差异时才会更改React节点,如一个节点,如果渲染之间从父组件接受到了不同的props,此时该组件才会发生重新渲染。 + +## state快照 +在渲染函数中,state的快照是不可变的,即使在调用setState函数将更新state后,旧组件中获取的state值仍然没有变化。 +```js +// 即使调用setTitle,此快照中的title值在setTitle之前和之后仍然没有变化 +// ,而新渲染的组件title初始值则为改变之后的值 +function Title() { + const [title,setTitle]=useState('Morning News'); + + return ( +
    +

    {title}

    + +
    + ) +} +``` +## 向setState中传入更新函数 +react支持向setState中传入更新函数而不是更新后的值,例如 +```js +setNumber(n => n + 1); +setNumber(n => n + 1); +setNumber(n => n + 1); +``` +此时react会将上述三个函数以此加入到队列中,并在下次渲染时遍历执行队列中的函数。 + +## 更新state对象 +如果向useState中传入object,那么在调用setState函数时,则是应该传入一个新的对象,而不是在原有state对象上进行更新。 +**应该将state对象看作是不可变的,调用setState时,应该创建一个state对象的副本,并且修改副本对象后用副本对象的值去更新setState方法。** +```js +// 如果想要修改对象中的某个字段,可以使用如下方法 +let oldObj = { + name : 'kazusa', + isMale: false, +}; +let newObj = { + // 展开对象中的属性 + ...odlObj, + // 新设置某个属性,用于覆盖旧的值 + name:'mashiro', +} +``` +### 修改嵌套对象中的属性 +```js +setPerson({ + ...person, // Copy other fields + artwork: { // but replace the artwork + ...person.artwork, // with the same one + city: 'New Delhi' // but in New Delhi! + } +}); +``` +## Immer +如果要修改深层嵌套的state值,可以引入Immer库来完成对象的拷贝工作。通过Immer库,可以无需关心对象不可变,而是直接以可变的语法来修改对象属性,而Immer会实际帮忙处理对象不可便的工作。 +```js +// 通过该import代替react中useState +import { useImmer } from 'use-immer'; + +// 然后可以直接修改对象中的值 +const [person, updatePerson] = useImmer({ + name: 'Niki de Saint Phalle', + artwork: { + title: 'Blue Nana', + city: 'Hamburg', + image: 'https://i.imgur.com/Sd1AgUOm.jpg', + } + }); + +function handleNameChange(e) { + updatePerson(draft => { + draft.name = e.target.value; + }); + } +``` + +## 更新state数组 +和object一样,在react中数组应该也要是不可变的,在更新state中的值时,也应该再创建一个新的数组,并用新的数组值设置