React

React

gaoyanchen Lv3

colocation

自动嵌套

  • 自动嵌套: 当你在**/dashboard**目录下创建页面时,这些页面会自动作为**children**传递给**<Layout />**组件。这意味着这些页面会被渲染在布局组件定义的结构中。

route groups

state如同一张快照

设置 state 只会为下一次渲染变更 state 的值。在第一次渲染期间,number0。这也就解释了为什么在 那次渲染中的onClick 处理函数中,即便在调用了 setNumber(number + 1) 之后,number 的值也仍然是 0

1
2
3
4
5
6
7
8
9
<button onClick={() => {

setNumber(number + 1);

setNumber(number + 1);

setNumber(number + 1);

}}>+3</button>

以下是这个按钮的点击事件处理函数通知 React 要做的事情:

  1. setNumber(number + 1)number 0 所以 setNumber(0 + 1)
    • React 准备在下一次渲染时将 number 更改为 1
  2. setNumber(number + 1)number 0 所以 setNumber(0 + 1)
    • React 准备在下一次渲染时将 number 更改为 1
  3. setNumber(number + 1)number 0 所以 setNumber(0 + 1)
    • React 准备在下一次渲染时将 number 更改为 1

尽管你调用了三次 setNumber(number + 1),但在 这次渲染的 事件处理函数中 number 会一直是 0,所以你会三次将 state 设置成 1。这就是为什么在你的事件处理函数执行完以后,React 重新渲染的组件中的 number 等于 1 而不是 3

随时间变化的 state

一个 state 变量的值永远不会在一次渲染的内部发生变化, 即使其事件处理函数的代码是异步的。在 那次渲染的<font style="color:#DF2A3F;">onClick</font> 内部,<font style="color:#DF2A3F;">number</font> 的值即使在调用 <font style="color:#DF2A3F;">setNumber(number + 5)</font> 之后也还是 <font style="color:#DF2A3F;">0</font>。它的值在 React 通过调用你的组件“获取 UI 的快照”时就被“固定”了。

state

像这样的代码是有问题的,因为它改变了 state 中现有的对象:

1
2
3
position.x = e.clientX;

position.y = e.clientY;

但是像这样的代码就 没有任何问题,因为你改变的是你刚刚创建的一个新的对象:

1
2
3
4
5
6
7
const nextPosition = {};

nextPosition.x = e.clientX;

nextPosition.y = e.clientY;

setPosition(nextPosition);

事实上,它完全等同于下面这种写法:

1
2
3
4
5
6
7
setPosition({

x: e.clientX,

y: e.clientY

});

只有当你改变已经处于 state 中的 现有 对象时,mutation 才会成为问题。而修改一个你刚刚创建的对象就不会出现任何问题,因为 还没有其他的代码引用它。改变它并不会意外地影响到依赖它的东西。这叫做“局部 mutation”。你甚至可以 在渲染的过程中 进行“局部 mutation”的操作。这种操作既便捷又没有任何问题!

setPerson({

  ...person,

  email: e.target.value

});

请注意 ... 展开语法本质是是“浅拷贝”——它只会复制一层。这使得它的执行速度很快,但是也意味着当你想要更新一个嵌套属性时,你必须得多次使用展开语法。

immer

通过使用 Immer,你写出的代码看起来就像是你“打破了规则”而直接修改了对象:

1
2
3
4
5
6
7
  const [person, updatePerson] = useImmer(.....)

updatePerson(draft => {

draft.artwork.city = 'Lagos';

});

但是不同于一般的 mutation,它并不会覆盖之前的 state!

请注意当使用 Immer 时,类似 **artwork.seen = nextSeen** 这种会产生 mutation 的语法不会再有任何问题了:

1
2
3
4
5
6
7
updateMyTodos(draft => {

const artwork = draft.find(a => a.id === artworkId);

artwork.seen = nextSeen;

});

这是因为你并不是在直接修改原始的 state,而是在修改 Immer 提供的一个特殊的 draft 对象。同理,你也可以为 draft 的内容使用 push()pop() 这些会直接修改原值的方法。

在幕后,Immer 总是会根据你对 draft 的修改来从头开始构建下一个 state。这使得你的事件处理程序非常的简洁,同时也不会直接修改 state。

==和===

<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useCallback</font> <font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useMomeo</font> 的区别

**<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useCallback</font>** **<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useMemo</font>** 都是用于性能优化的 React 钩子函数,它们都可以避免不必要的重新计算或重新渲染。虽然它们看起来很相似,但它们有几个重要的区别。

首先,**<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useCallback</font>** 返回一个缓存的回调函数,而 **<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useMemo</font>** 返回一个缓存的值。这意味着 **<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useCallback</font>** 的主要作用是为一个函数创建缓存,而 **<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useMemo</font>** 的主要作用是缓存一个值。

其次,它们接受的参数不同。**<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useCallback</font>** 接受一个回调函数和一个依赖项数组,而 **<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useMemo</font>** 接受一个函数和一个依赖项数组。在 **<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useCallback</font>** 中,只有依赖项数组中的值发生变化时,才会重新创建回调函数。而在 **<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useMemo</font>** 中,只有依赖项数组中的值发生变化时,才会重新计算值。

最后,它们的使用场景也不同。**<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useCallback</font>** 适用于优化回调函数,避免不必要的重新渲染,并传递给子组件。而 **<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useMemo</font>** 适用于优化计算开销较大的值,如大型数组或对象的计算。

综上所述,**<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useCallback</font>****<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">useMemo</font>** 的主要区别在于它们的返回值类型和使用场景。需要根据具体的情况选择使用哪个钩子函数。

  • Title: React
  • Author: gaoyanchen
  • Created at : 2024-09-13 19:07:05
  • Updated at : 2024-10-17 11:24:02
  • Link: https://gyc.660624.xyz/2024/09/13/React/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments