React
colocation

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


route groups

state如同一张快照
设置 state 只会为下一次渲染变更 state 的值。在第一次渲染期间,number 为 0。这也就解释了为什么在 那次渲染中的onClick 处理函数中,即便在调用了 setNumber(number + 1) 之后,number 的值也仍然是 0:
1 | <button onClick={() => { |
以下是这个按钮的点击事件处理函数通知 React 要做的事情:
setNumber(number + 1):number是0所以setNumber(0 + 1)。- React 准备在下一次渲染时将
number更改为1。
- React 准备在下一次渲染时将
setNumber(number + 1):number是0所以setNumber(0 + 1)。- React 准备在下一次渲染时将
number更改为1。
- React 准备在下一次渲染时将
setNumber(number + 1):number是0所以setNumber(0 + 1)。- React 准备在下一次渲染时将
number更改为1。
- React 准备在下一次渲染时将
尽管你调用了三次 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 | position.x = e.clientX; |
但是像这样的代码就 没有任何问题,因为你改变的是你刚刚创建的一个新的对象:
1 | const nextPosition = {}; |
事实上,它完全等同于下面这种写法:
1 | setPosition({ |
只有当你改变已经处于 state 中的 现有 对象时,mutation 才会成为问题。而修改一个你刚刚创建的对象就不会出现任何问题,因为 还没有其他的代码引用它。改变它并不会意外地影响到依赖它的东西。这叫做“局部 mutation”。你甚至可以 在渲染的过程中 进行“局部 mutation”的操作。这种操作既便捷又没有任何问题!
…
setPerson({
...person,
email: e.target.value
});
请注意 ... 展开语法本质是是“浅拷贝”——它只会复制一层。这使得它的执行速度很快,但是也意味着当你想要更新一个嵌套属性时,你必须得多次使用展开语法。
immer
通过使用 Immer,你写出的代码看起来就像是你“打破了规则”而直接修改了对象:
1 | const [person, updatePerson] = useImmer(.....) |
但是不同于一般的 mutation,它并不会覆盖之前的 state!
请注意当使用 Immer 时,类似 **artwork.seen = nextSeen** 这种会产生 mutation 的语法不会再有任何问题了:
1 | updateMyTodos(draft => { |
这是因为你并不是在直接修改原始的 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.


