写点什么

几天不写 React,已经看不懂语法了

  • 2023-07-07
    福建
  • 本文字数:1594 字

    阅读完需:约 5 分钟

几天不写React,已经看不懂语法了

下面这个React组件代码,用到 3 个use关键词,你理解他们的作用吗?

'use client'
function App() { using data = use(ctx); // ...}
复制代码

真是几天不写React,语法都看不懂了。本文就来聊聊这几个use关键词各自的意义。

欢迎加入人类高质量前端交流群,带飞

use client

首先是位于代码顶部的'use client'声明,使用方式类似于严格模式的声明:

'use strict';// 此处是严格模式下的JavaScript代码
复制代码

'use client'声明是RSCReact Server Component,服务端组件)协议中的定义。

启用了RSCReact应用,所有组件默认在服务端渲染(可以通过Next v13体验),只有声明'use client'的组件文件,会在前端渲染。

假设我们的React应用组件结构如下,其中红色代表服务端组件,蓝色代表客户端组件(声明'use client'):



那么当应用打包后,D、E 组件会打包成独立文件。在前端,React可以直接渲染 A、B、C 组件。但是对于 D、E,需要以JSONP的形式请求回组件代码再渲染。

完整执行逻辑如下:



using 关键字

接下来是data变量前的using关键字:

using data = use(ctx);
复制代码

using关键字是tc39提案ECMAScript Explicit Resource Management提出的,用于为各种资源(内存、I/O等)提供统一的生命周期管理(何时分配、何时释放等)。

同时,TS v5.2率先引入了这个关键字。所以,接下来的讲解我们以TS中的using关键词为准。

using的作用有点类似useEffectdestroy函数。当我们在useEffectcreate函数绑定了事件后,可以在destroy函数解绑:

function App() {  useEffect(() => {    console.log('这里是create函数')    return () => {      console.log('这里是destroy函数')    }  }, [])}
复制代码

类似的,当我们通过using关键词声明一个包含[Symbol.dispose]方法的对象后,当离开当前作用域时,声明的[Symbol.dispose]方法会执行:

{  const getResource = () => {    return {      [Symbol.dispose]: () => {        console.log('离开啦!')      }    }  }  using resource = getResource();}// 代码执行到这里会打印 离开啦!
复制代码

[Symbol.dispose]方法内主要执行一些释放资源的操作。

比如,当我们操作数据库时,如果要考虑操作完断开数据库连接,可能会写出如下代码:

const db = await connectDB();try {  // 执行数据库操作} finally {  // 断开数据库连接  await db.close();}
复制代码

如果使用using关键词,代码如下:

const connect = async () => {  const db = await connectDB();  return {    db,    [Symbol.asyncDispose]: () => db.close()  };};
// 使用{ using { db } = await connect(); // 执行数据库操作} // 离开作用域自动断开连接
复制代码

配合async await使用,可以降低由于忘记释放资源造成内存泄漏的可能性。

use 方法

最后是React v18.3之后发布的新原生hook —— use

using data = use(ctx);
复制代码

这个hook可以接收两种类型数据:

  • React Context

此时use的作用与useContext一样。

  • promise

此时如果这个promise处于pending状态,则最近一个祖先<Suspense/>组件可以渲染fallback

比如,在如下代码中,如果<Cpn />组件或其子孙组件使用了use,且promise处于pending状态(比如请求后端资源):

function App() {  return (    <div>      <Suspense fallback={<div>loading...</div>}>        <Cpn />      </Suspense>    </div>  );}
复制代码

那么,页面会渲染如下结果:

<div>  <div>loading...</div></div>
复制代码

当请求成功后,会渲染<Cpn />

总结

对于开篇提到的代码:

'use client'
function App() { using data = use(ctx); // ...}
复制代码

表示:

  • 这是个客户端组件

  • 如果传递给use的变量ctxReact Context,则use的作用等同于useContext

  • 如果传递给use的变量ctxpromise,则配合最近的<Suspense/>使用

  • 如果use的返回值包含[Symbol.dispose],则App组件render完成后会执行[Symbol.dispose]方法

一个文件,三款use相关语法,你是不是已经懵逼了呢?

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
几天不写React,已经看不懂语法了_伤感汤姆布利柏_InfoQ写作社区