react16前

渲染架构是同步递归,无法中断。

react16

  • 革命性升级:Fiber架构:把递归改成链表结构,可中断渲染,为并发渲染打好基础。

  • 除了底层的重构,React 16 也带来了一系列直接影响开发方式的新特性。

    特性 说明 解决了什么问题
    Error Boundaries (错误边界) static getDerivedStateFromError() 和 componentDidCatch() 两个生命周期方法,创建一个能捕获其子组件树中 JavaScript 错误的组件 局部容错:之前组件内的一个 JS 错误会导致整个 React 应用崩溃,现在可以用错误边界包裹特定区域,显示一个降级的备用 UI,而不会影响应用的其他部分
    Portals (传送门) ReactDOM.createPortal(child, container) 允许将子节点渲染到父组件 DOM 层级之外的 DOM 节点中 跳出 DOM 层级限制:完美解决了模态框(Modal)、提示框(Tooltip)、悬浮菜单等需要从视觉上“突破”父容器(如 overflow: hidden)的组件的渲染问题
    render 方法的新返回类型 组件的 render 函数现在可以直接返回数组和字符串,而不再强制要求被一个单一的根元素包裹 告别“Div 地狱”:避免了在组件外层套一个无意义的
    ,让 DOM 结构更干净,尤其在返回一组并列元素时非常有用。React 16.2 后更是推荐使用 <React.Fragment> 或 <> </> 语法,语义更清晰
    React.memo 一个高阶组件,用于函数组件,通过浅层比较 props 来决定是否跳过重新渲染,从而提升性能 函数组件的性能优化:此前只有类组件可以通过继承 PureComponent 实现类似功能,React.memo 将这一性能优化能力赋予了函数组件。

react17

是一个“没有新特性”的版本,过渡版本,重写时间系统。为了降低 React 自身的升级门槛,为未来的版本(尤其是 React 18 的并发特性)铺平道路

react18

1)并发模式

可中断,可恢复,可丢弃,优先响应用户交互

2)自动批处理

以前只有react事件才会批处理,比如onClick onChange。
现在所有异步都可批处理:fetch/setTimeOut/promise 批处理一次render。

3)Transitions(过渡更新) 优先级控制

区分紧急更新和非紧急更新,API:startTransition,useTransition。
示例:

1
2
3
4
5
6
7
8
9
10
// hooks用法 isPending:表示是否有过渡更新正在执行
const [isPending, startTransition] = useTransition();
function handleChange(e) {
// 优先更新input ->高优先级
setInput(e.target.value);
// 搜索列表慢慢渲染 ->低优先级
startTransition(() => {
setList(filterList(e.target.value));
});
}

4)新的hooks

  • useId:生成稳定性唯一ID,完美支持SSR和无障碍访问。

  • useDeferredValue(延迟渲染某些值):
    适用于搜索,大列表
    例子:

    1
    2
    3
    // input实时更新 列表慢一点更新
    const deferredText = useDeferredValue(text)
    <MySlowList text={deferredText} />
  • useTransition(以上有说到用法)

  • useSyncExternalStore:安全订阅外部数据源
    react18的并发模式可能会导致状态撕裂,ui显示数据不一致,所以外部状态源例如redux,zustand要保证并发模式的一致性。

5)Suspense SSR支持 + Streaming

suspense支持服务器渲染,以前 ssr必须等全部数据,现在:

1
2
3
组件1 ready -> 先返回
组件2 loading -> fallback
组件2 ready -> 再流式返回

Nextjs中的运用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { Suspense } from "react";

// 这是一个需要异步获取数据的组件
async function Comments() {
// 模拟慢速数据请求
const res = await fetch("https://api.example.com/comments", {
cache: "no-store",
});
const comments = await res.json();
return (
<ul>
{comments.map((comment) => (
<li key={comment.id}>{comment.text}</li>
))}
</ul>
);
}

export default function BlogPost() {
return (
<div>
<h1>我的博客文章</h1>
<p>这是文章的快速主体部分,会立即发送到浏览器。</p>

{/* 用 Suspense 包裹评论组件 */}
<Suspense fallback={<div>正在加载评论...</div>}>
<Comments />
</Suspense>
</div>
);
}

react19(核心是全栈化)

19引入Server components和Actions,让React从前端框架演进为全栈解决方案。
1️⃣ Server Components:组件可以在服务端执行

2️⃣ Actions(革命性):可直接在组件里面写后端逻辑,不用fetch:

1
<form action={async (formData) => {}}>

3️⃣ use hook(直接 await)

1
2
3
4
5
6
7
import { use } from "react";

function Page() {
const data = use(fetch("/api/data").then((res) => res.json()));

return <div>{data.name}</div>;
}

4️⃣ 表单能力增强: useActionState useFormStatus
React 以前处理表单提交非常麻烦,需要 loading / error / state 手动管理

1)useActionState的用法 (管理表单 action 执行后的状态。)

以前写法

1
2
const [loading, setLoading] = useState(false);
const [data, setData] = useState(null);

现在写法

1
2
// action为表单提交的函数,initialState为初始状态 state(action返回的数据), formAction(绑定给 form), isPending(是否正在提交)
const [state, formAction, isPending] = useActionState(action, initialState);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { useActionState } from "react";

async function submitForm(prevState, formData) {
const name = formData.get("name");

return {
message: `Hello ${name}`,
};
}

export default function Form() {
const [state, formAction, isPending] = useActionState(submitForm, {
message: "",
});

return (
<form action={formAction}>
<input name="name" />

<button disabled={isPending}>Submit</button>

<p>{state.message}</p>
</form>
);
}

2)useFormStatus的用法 (获取表单的提交状态)

用法示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// SubmitButton组件
import { useFormStatus } from "react-dom";

function SubmitButton() {
const { pending } = useFormStatus();

return (
<button disabled={pending}>{pending ? "Submitting..." : "Submit"}</button>
);
}
// Form组件
function Form() {
return (
<form action={saveUser}>
<input name="name" />

<SubmitButton />
</form>
);
}