You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
interfaceLoadingProps{// 你会注意到这里没有 `children` 属性 - 这就是出现错误的原因noHeader?: boolean;}// if props.noHeader is true then this component returns just the icon and a message// if props.noHeader is true then this component returns the same but wrapped in an h1constLoading: React.FunctionComponent<LoadingProps>=(props)=>props.noHeader ? (<><FontAwesomeIconicon={faSnowflake}spin/> Loading {props.children} ...</>) : (<h1className="loader"><FontAwesomeIconicon={faSnowflake}spin/> Loading {props.children} ...</h1>
);
为了支持React 18,React类型定义进行了升级,其中包含了一些break change。本文将讲述在TypeScript中如何升级到React 18
React 18和Definitely Typed
在alpha和beta测试经历了相当长的一段时间后,React 18 于2022年3月29日正式发布。在第一个alpha版本发布的时候,TypeScript就提供了支持
这是通过Definitely Typed(一个社区维护的各种TypeScript类型定义的库)的类型定义实现的)来使用。感谢Sebastian Silbermann的贡献,他在React18的类型定义工作中投入了大量的精力
目前React 18已经发布并且React 18 的类型定义在 Sebastian 的pr合并后也进行了更新。许多项目会面临一些break change。本文章将介绍会产生哪些break change及如何解决
Definitely Typed和语义版本控制
开发者习惯于在使用的软件中进行语义版本控制。通常来说在主版本的修改是表明有重大更改的。这正是React从v17升级到v18所做的事
Definitely Typed
是不支持语义版本控制的这不是故意的。因为
Definitely Typed
特意将类型定义发布到npm的@types
作用域下。例如,React的类型定义被发布到@types/react
需要注意的是,npm 建立在语义版本控制之上。为了使类型定义的使用更容易,类型定义包的版本将等同于它支持的 npm 包的版本。对于
react
的18.0.0
,对应的类型定义是@types/react
的18.0.0
如果
@types/react
类型定义发生breaking change,则会发布新版本而不是增加主要或次要版本号修改将仅应用于修订号。这样做是为了通过npm维护当前更简单的类型消费模型
React 18: 类型上的breaking change
综上所述,对于那些被广泛使用的类型定义包,都会尽量减少产生breaking change
顺便说一句,
Definitely Typed
自动化工具将类型定义分为三类: "深受大家喜爱(Well-liked by everyone)"、"流行(Popular)"和"关键(Critical)"。感谢Andrew Branch的分享。被广泛使用的React被认为是"关键的"当Sebastian提交了一个pr来升级TypeScript的React类型定义时,就有机会来做一些重大的修改。这些修改可能并不都与React 18有直接关系但会修复React类型定义中长期存在的一些问题
Sebastian pr非常好,我建议你去看一下。以下是重大更改的摘要
ReactFragment
中的{}
(related to 1.)this.context
变成unkown
noImplicitAny
应用到useCallback
在上述修改中,移除隐式children是最具破坏性的。Sebastian专门写了一篇博客来解释其原因。他还写了一个codemod来有利于进行这个代码迁移
下面让我们开始将代码库的react升级到18吧!
升级
我将通过升级我阿姨的网站进行演示。这是一个简单的网站,升级的pr
首先在
package.json
中升级React然后升级类型定义
升级的时候需要检查lock依赖(yarn.lock / package-lock.json等),确保只有18版本的
@types/react
和react
。现在依赖安装已完成,会看到以下报错
代码如下
在这里看到的是去除隐式
children
的改动。在我们进行升级之前,所有React.Component
和React.FunctionComponent
都有一个children
属性,它允许React
用户在不声明children
的情况下直接使用升级18后就不一样了。如果有一个带有子组件,则必须显式声明这个组件的类型
在这个例子中,通过直接添加
children
属性的声明可以修复这个问题但是,当可以让其他方式帮我们写代码的话,为什么还要写代码呢?
我们可以使用Sebastian开发的codemod来替代手动修改代码。使用它直接通过以下的命令就可以:
执行后,会看到如下提示:
选择
a
并让codemod运行。对于这个项目,有37个文件更新了。所有文件都需要进行相同的修改。在每种情况下,组件的props
都被React.PropsWithChildren
包起来。例如Loading
组件如下PropsWithChildren
仅仅是将children
属性添加,如下这就解决了上面遇到的编译问题,没有类型问题报错了
总结
通过本文我们已经学习到React 18是如何出现类型的破坏性更改,并知道可以使用codemod快速进行升级
The text was updated successfully, but these errors were encountered: