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
虽然两种方式都差不多,但我个人更喜欢使用 React.FC 的方式来创建我的有类型约束的函数式组件,它还支持 children 的传入,即使在我们的类型中并没有定义它:
exportconstUser:React.FC<UserInfo>=({ name, age, children })=>{return(<divclassName="User"><p>{name}</p><p>{age}</p><div>{children}</div></div>)}constuser=<Username='vortesnail'age={25}>I am children text!</User>
我们也并不需要把所有参数都显示地解构:
exportconstUser:React.FC<UserInfo>=(props)=>{return(<divclassName="User"><p>{props.name}</p><p>{props.age}</p><div>{/* 仍可以拿到 children */}{props.children}</div></div>)}constuser=<Username='vortesnail'age={25}>I am children text!</User>
好了,我们暂时知道上面这么多,就可以开始使用我们的 hooks 了~
我将从三个点阐述如何结合 typescript 使用我们的 hooks :
为啥使用❓
怎么使用🛠
场景例举📖
useState
为啥使用useState?
可以让函数式组件拥有状态管理特性,类似 class 组件中的 this.state 和 this.setState ,但是更加简洁,不用频繁的使用 this 。
importReact,{useRef}from'react'constTextInput=()=>{constinputEl=useRef<HTMLInputElement>(null)constonFocusClick=()=>{if(inputEl&&inputEl.current){inputEl.current.focus()}}return(<div><inputtype="text"ref={inputEl}/><buttononClick={onFocusClick}>Focus the input</button></div>)}exportdefaultTextInput
constShow:React.FC<Data> = ({time,children}) =>{//...constgetNewTime=useCallback(()=>{returnchangeTime(time)},[time])return(<div><p>Time is: {getNewTime()}</p><p>Random is: {children}</p></div>)}
exportconstColorContext=React.createContext({color: '#1890ff'})const{ color }=useContext(ColorContext)// 或exportconstColorContext=React.createContext(null)<ColorContext.Providervalue='#1890ff'><App/></ColorContext.Provider>
// App 或以下的所有子组件都可拿到 valueconstcolor=useContext(ColorContext)// '#1890ff'
场景举例
1.根组件注册,所有子组件都可拿到注册的值:
importReact,{useContext}from'react'constColorContext=React.createContext<string>('')constApp=()=>{return(<ColorContext.Providervalue='#1890ff'><Father/></ColorContext.Provider>)}constFather=()=>{return(<Child/>)}constChild=()=>{constcolor=useContext(ColorContext)return(<divstyle={{backgroundColor: color}}>Background color is: {color}</div>)}exportdefaultApp
看人家
Typescript
和React hooks
耍的溜的飞起,好羡慕啊~🥺那来吧,这篇爽文从脑壳到jio干地教你如何使用这两大利器开始闪亮开发!✨
课前预知
🌸我觉得比较好的学习方式就是跟着所讲的内容自行实现一遍,所以先启个项目呗~
在
src/App.tsx
内引用我们的案例组件,在src/example.tsx
写我们的案例组件。🌸函数式组件的使用~
我们可以通过以下方式使用有类型约束的函数式组件:
也可以通过以下方式使用有类型约束的函数式组件:
上述代码中不同之处在于:
虽然两种方式都差不多,但我个人更喜欢使用
React.FC
的方式来创建我的有类型约束的函数式组件,它还支持children
的传入,即使在我们的类型中并没有定义它:我们也并不需要把所有参数都显示地解构:
好了,我们暂时知道上面这么多,就可以开始使用我们的 hooks 了~
我将从三个点阐述如何结合
typescript
使用我们的hooks
:useState
为啥使用useState?
可以让函数式组件拥有状态管理特性,类似 class 组件中的
this.state
和this.setState
,但是更加简洁,不用频繁的使用this
。怎么使用useState?
场景举例
1.参数为基本类型时的常规使用:
2.参数为对象类型时的使用:
在我们的参数为对象类型时,需要特别注意的是,
setXxx
并不会像this.setState
合并旧的状态,它是完全替代了旧的状态,所以我们要实现合并,可以这样写(虽然我们以上例子不需要):useEffect
为啥使用useEffect?
你可以把
useEffect
看做componentDidMount
,componentDidUpdate
和componentWillUnmount
这三个函数的组合。怎么使用useEffect?
场景举例
1.每当状态改变时,都要重新执行
useEffect
的逻辑:2.即使每次状态都改变,也只执行第一次
useEffect
的逻辑:3.根据某个状态是否变化来决定要不要重新执行:
因为
value
我们不会去任何地方改变它的值,所以在末尾加了[value]
后,useEffect
内的逻辑也只会执行第一次,相当于在 class 组件中执行了componentDidMount
,后续的shouldComponentUpdate
返回全部是false
。4.组件卸载时处理一些内存问题,比如清除定时器、清除事件监听:
useRef
为啥使用useRef?
它不仅仅是用来管理 DOM ref 的,它还相当于 this , 可以存放任何变量,很好的解决闭包带来的不方便性。
怎么使用useRef?
场景举例
1.闭包问题:
想想看,我们先点击 加 按钮 3 次,再点 弹框显示 1次,再点 加 按钮 2 次,最终
alert
会是什么结果?结果是弹框内容为 current count: 3 ,为什么?
**
那如何显示最新的当前 count 呢?
2.因为变更
.current
属性不会引发组件重新渲染,根据这个特性可以获取状态的前一个值:我们可以看到,显示的总是状态的前一个值:
3.操作 Dom 节点,类似 createRef():
useMemo
为啥使用useMemo?
从 useEffect 可以知道,可以通过向其传递一些参数来影响某些函数的执行。 React 检查这些参数是否已更改,并且只有在存在差异的情况下才会执行此。
useMemo 做类似的事情,假设有大量方法,并且只想在其参数更改时运行它们,而不是每次组件更新时都运行它们,那就可以使用 useMemo 来进行性能优化。
怎么使用useMemo?
场景举例
1.常规使用,避免重复执行没必要的方法:
我们先来看一个很简单的例子,以下是还未使用
useMemo
的代码:在这个例子中,无论你点击的是 获取当前时间 按钮还是 获取当前随机数 按钮,
<Show />
这个组件中的方法changeTime
都会执行。但事实上,点击 获取当前随机数 按钮改变的只会是
children
这个参数,但我们的changeTime
也会因为子组件的重新渲染而重新执行,这个操作是很没必要的,消耗了无关的性能。使用
useMemo
改造我们的<Show />
子组件:这个时候只有点击 获取当前时间 才会执行
changeTime
这个函数,而点击 获取当前随机数 已经不会触发该函数执行了。2.你可能会好奇,
useMemo
能做的难道不能用useEffect
来做吗?答案是否定的!如果你在子组件中加入以下代码:
你会发现,控制台会打印如下信息:
正如我们一开始说的:传入
useMemo
的函数会在渲染期间执行。在此不得不提
React.memo
,它的作用是实现整个组件的Pure
功能:所以简单用一句话来概括
useMemo
和React.memo
的区别就是:前者在某些情况下不希望组件对所有props
做浅比较,只想实现局部Pure
功能,即只想对特定的props
做比较,并决定是否局部更新。useCallback
为啥使用useCallback?
useMemo
和useCallback
接收的参数都是一样,都是在其依赖项发生变化后才执行,都是返回缓存的值,区别在于useMemo
返回的是函数运行的结果,useCallback
返回的是函数。怎么使用useCallback?
场景举例
将之前
useMemo
的例子,改一下子组件以下地方就OK了:useReducer
为什么使用useReducer?
有没有想过你在某个组件里写了很多很多的
useState
是什么观感?比如以下:怎么使用useReducer?
场景举例:
与
useContext
结合代替 Redux 方案,往下阅读。useContext
为啥使用useContext?
简单来说
Context
的作用就是对它所包含的组件树提供全局共享数据的一种技术。怎么使用useContext?
场景举例
1.根组件注册,所有子组件都可拿到注册的值:
2.配合
useReducer
实现 Redux 的代替方案:以上此方案是值得好好思索的,特别是因为 TypeScript 而导致的类型约束!
当然,如果有更好的解决方案,希望有大佬提出来,我也可以多学习学习~
结语
最近也是看了许多好文章,多谢各位掘金的大佬的无私奉献,本篇文章的灵感来源也是最近蛮火的一篇文章:
这篇文章写的通俗易懂,但是没有涉及到在 Typescript 中的使用,且我在掘金上也搜不到类似的带入门的文章,故决定自己写一篇,希望能帮助到一些朋友,也能补足下自己的知识点。
参考文章:
TypeScript and React
终于搞懂 React Hooks了!!!!!
用 useContext + useReducer 替代 redux
React Hooks Tutorial on pure useReducer...
好东西不能独享,我在此强烈推荐一篇从零搭建 React + Typescript 开发环境的系列文章给大家,这是我看到过写的最清楚且优质的环境搭建文章,大家可以去看看,绝对收获满满:
从零开始配置 react + typescript(一):dotfiles
从零开始配置 react + typescript(二):linters 和 formatter
从零开始配置 react + typescript(三):webpack
The text was updated successfully, but these errors were encountered: