Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
minmaxw1024 committed Nov 23, 2024
2 parents 5591b97 + 66145af commit ccb255e
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 0 deletions.
117 changes: 117 additions & 0 deletions posts/relearn_react_06_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
title: 重新学习 React 06
published_at: 2024-11-19T15:00:00.000Z
snippet: 从 react.dev 重新学习 React
---

## 来自 "State:组件的记忆"

### 为什么我们需要"state"而不是使用局部变量?

- 改变局部变量不会触发重新渲染
- React 不会在重新渲染之间保持局部变量

### React 中的"state"是什么?

使用 `useState` hooks 生成两个变量:`count``setCount`

`count` 是状态变量,用于_保持_值。

`setCount` 是状态设置函数,用于_更新_值。

### 为什么 React useState 使用数组解构?

1. 数组数据结构将变量数量限制为两个。我们只能从 `useState` 数组解构中获得两个变量,如果添加更多变量,会出现错误。

2. 数组解构允许灵活命名变量。你可以随意命名这些变量。

```jsx
// 这些是等价的:
const [user, setUser] = useState(null);
const [isOpen, setIsOpen] = useState(false);
```

3. 显然比单独返回它们更好。

## 来自 "渲染和提交"

### React 组件生命周期的 3 个阶段

### 触发

- 初始渲染
- 重新渲染(状态改变,属性改变)

### 渲染

- 初始渲染(根组件)
- 重新渲染(递归调用状态更新触发渲染的函数组件)

### 提交

- 初始渲染(使用 `appendChild` 将元素添加到 DOM)
- 重新渲染(对 DOM 应用最小的更改)

React 只在渲染之间有差异时才更改 DOM 节点。

## 常见陷阱

### Hooks 只能在函数组件的顶层调用。

1. 我们不能在循环、条件或嵌套函数中使用 hooks。
2. 我们不能在类组件中使用 hooks。

只能在函数组件的_顶层_使用。

### 渲染必须始终是纯计算

再次强调,使用纯函数作为组件。相同输入,相同输出。并保持每个组件简单且专注,以避免组件复杂度增长后可能出现的 bug。

## 深入理解

### React 如何知道要返回哪个状态?

Hooks 依赖于同一组件每次渲染时的稳定调用顺序。

```tsx
type StatePair<T> = [T, (nextState: T) => void];
let componentHooks: StatePair<any>[] = [];
let currentHookIndex = 0;

// useState 在 React 内部的工作原理(简化版)
function useState<T>(initialState: T) {
let pair = componentHooks[currentHookIndex];
if (pair) {
// 这不是第一次渲染,
// 所以状态对已经存在。
// 返回它并为下一个 Hook 调用做准备。
currentHookIndex++;
return pair;
}

// 这是我们第一次渲染,
// 所以创建一个状态对并存储它。
pair = [initialState, setState];

function setState(nextState: T) {
// 当用户请求状态更改时,
// 将新值放入对中。
pair[0] = nextState;
updateDOM();
}

// 存储这个对以供将来渲染使用
// 并为下一个 Hook 调用做准备。
componentHooks[currentHookIndex] = pair;
currentHookIndex++;
return pair;
}
```

### 性能优化 01

如果我们要更新的组件在树的很高位置,它会触发大量重新渲染。这不是一个好主意。

## 参考资料

- [React Hooks,没有魔法,只是数组](https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e)
45 changes: 45 additions & 0 deletions posts/relearn_react_07.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
title: Relearn React 07
published_at: 2024-11-20T15:00:00.000Z
snippet: Relearning React from react.dev
---

## From "State as a Snapshot"

State is defined inside a component but is managed by React, outside our
component. React keeps track of the state of each component and when the state
changes, React will re-render the component.

### What happens when state changes?

When the state of a component changes, React will re-render the component.

1. React calls your function again.
2. Your function returns a new JSX snapshot.
3. React then updates the screen(DOM) to match the snapshot your function
returned.

### What are includes in a snapshot?

A component "snapshot" includes the following:

- props
- event handlers
- local variables

It means, every render has its own props, event handlers, and local variables.

This is why in the below example, the alert number is 0, because this event
handler captures the state number at the time of the click event. Conversely, it
means every render has its own event handlers, props and state.

```jsx
# state number is 0

<button onClick={() => {
setNumber(number + 5);
setTimeout(() => {
alert(number);
}, 3000);
}}>+5</button>
```
43 changes: 43 additions & 0 deletions posts/relearn_react_07_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: 重新学习 React 07
published_at: 2024-11-20T15:00:00.000Z
snippet: 从 react.dev 重新学习 React
---

## 来自 "State 作为一个快照"

State 虽然定义在组件内部,但是由 React 在组件外部管理。React
会跟踪每个组件的状态,当状态发生变化时,React 会重新渲染该组件。

### 当状态改变时会发生什么?

当组件的状态发生变化时,React 会重新渲染该组件。

1. React 再次调用你的函数。
2. 你的函数返回一个新的 JSX 快照。
3. React 然后更新屏幕(DOM)以匹配你的函数返回的快照。

### 快照包含什么?

一个组件的"快照"包括以下内容:

- props(属性)
- 事件处理器
- 局部变量

这意味着,每次渲染都有其自己的 props、事件处理器和局部变量。

这就是为什么在下面的例子中,alert 数字是
0,因为这个事件处理器捕获了点击事件时的状态数字。反过来说,这意味着每次渲染都有其自己的事件处理器、props
和状态。

```jsx
# 状态数字是 0

<button onClick={() => {
setNumber(number + 5);
setTimeout(() => {
alert(number);
}, 3000);
}}>+5</button>
```

0 comments on commit ccb255e

Please sign in to comment.