React进阶用法和hooks的个人使用见解(Typescript版本) - 2.hooks的useState、useEffect、自定义钩子的实际使用

TypeScript 同时被 2 个专栏收录
22 篇文章 0 订阅
11 篇文章 1 订阅

2.hooks的useState、useEffect的实际使用(Typescript)

注意:hooks只能在函数(无状态组件)中使用

从React16.8版本的hooks正式发布,hooks的使用是越来越火,从而出现了许多使用无状态组件(函数)+hooks替代有状态组件(类)来书写React组件的热潮,但是由于一些实际运用还有些缺乏,接下来介绍一下useState、useEffect两个hooks的一些简单使用吧

2.1 useState:官方文档就表明出,这个钩子就是在函数中能使用和class的state一样的状态管理,使用方式也较为简单,就不用做过多的介绍,直接上代码

简单的双向数据绑定

import React, { useState } from 'react';
export default (): JSX.Element => {
    //在typescript中,useState是一个泛型函数,可以传入对应的类型
    const [count, setCount] = useState<number>(100);
    return (
        <>
            <h2>{count}</h2>
            <button onClick={()=>setCount(count + 1)}>++</button>
	         {/*   还可以传入回调函数 */}
            <button onClick={()=>setCount((count:number)=>(count - 1))}>--</button>
        </>
    )
}

由于useState返回一个数组,第一个count参数就与有状态组件(类)中的state很相似,是无法改变的值,而第二个参数setCount就与有状态组件的setState差不多,较为简单

2.2 useEffect 一个相当于,状态组件中componentDidMount + componentDidUpdate + componentWillUnmount三个钩子函数的结合体 ,如果不清楚的可以看 React有状态组件生命周期的官方中文介绍

2.2.1 通过useEffect+useState发送请求,获取数据

import React,{ useEffect,useState } from 'react';
export default ():JSX.Element => {
	const [status, setStatus] = useState<number>(400);//默认请求状态不成功
//当第二个参数是一个空数组,相当于一个componentDidMount,只有在render之后执行一次,之后不会执行,可以用于请求的发送
	useEffect(()=>{ //useEffect(async () =>{  })//这样使用是不正确的
		//注意:这里最好不要使用ES7的async await,除非你关闭了esLint检查,但是由于esLint是代码规范标准,遵守还是可以的
		axios.post('api-url').then(res=>res.json()).then(data=>console.log(data))
		//想使用async await的话,可以使用立即执行函数来包裹整个请求过程
		(async ()=>{
			const res= await axios.post('api-url').then(res=>res.json());
			setStatus(res.status);//假设后端返回的json中有这个属性
		})();
	},[]);
	return(
		<>
			<h2>请求状态</h2>
			<p>{status}</p>
		</>
	);
}

2.2.2 通过useEffect+useState实现定时器的触发

import React,{ useEffect,useState } from 'react';
export default ():JSX.Element => {
	//创建一个字符串state,存储当前系统时间
	const [date, setDate] = useState<string>(Date.now().toLocaleString());
	useEffect(() => {//使用useEffect,当date数据改变时,触发useEffect
        const times: NodeJS.Timeout = setInterval(() => setDate(Date.now().toLocaleString()), 1000);
        return ()=> {
            //这里的return返回的应该函数和componentWillUnmount差不多一致,在组件销毁前执行,防止定时器没有销毁
            clearInterval(times);//退出的时候清除定时器
        }
    }, [date]);//第二个参数中的数组,就是依赖项,会相当于有状态组件的componentWillReceiveProps,每次执行useEffect前会对date进行一次浅比较
	return(
		<>
			<h2>当前时间</h2>
			<p>{date}</p>
		</>
	);
}

从上面的案例可以知道,useEffect一开始执行了一次,与componentDidMount钩子函数的功能差不多一致,然后由于在定时器内部执行了setDate,改变了date的值,从而进行了一次对date的浅比较,发现改变后又一次执行useEffect(相当于componentDidUpdate),从而实现每秒执行一次的定时器

分页效果也是差不多这样的了,传入page和pageSize发送请求,当page或者pageSize发生改变的时候,触发useEffect,刷新数据,做到后端分页(只是不需要return一个函数销毁)
注意:当useEffect里面使用了外部的变量的情况下,需要在第二个数组参数中放入对应的变量,防止类似 React Hook useLayoutEffect has a missing dependency: 'options'. Either include it or remove the dependency array react-hooks/exhaustive-deps 的一些检查提示、代码规范.
当第二个参数不传递的情况下,就会发生只要数据发生改变就都会触发这个useEffect钩子,在一些比较特别的情况下可以使用,例如:收集用户操作数据等

2.3自定义钩子(官方介绍,自定义hooks需要以use开始才能正确的识别这是自定义钩子)

从上面的useEffect+useState的使用中可以看见,这样的组合是可以封装成一个自定义hooks来复用的

import React,{ useEffect,useState } from 'react';
const useDate = (initialDate:string)=> {//初始化时间
	//创建一个字符串state,存储当前系统时间
	const [date, setDate] = useState<string>();
	useEffect(() => {//使用useEffect,当date数据改变时,触发useEffect
        const times: NodeJS.Timeout = setInterval(() => setDate(Date.now().toLocaleString()), 1000);
        return ()=> {
            //这里的return返回的应该函数和componentWillUnmount差不多一致,在组件销毁前执行,防止定时器没有销毁
            clearInterval(times);//退出的时候清除定时器
        }
    }, [date]);//第二个参数中的数组,就是依赖项,会相当于有状态组件的componentWillReceiveProps,每次执行useEffect前会对date进行一次浅比较
    return { date };//由于外部只需要使用date,可以只暴露出这个数据
}

export default ():JSX.Element => {
	const { date } = useDate(Date.now().toLocaleString());//使用自定义钩子,获取返回的对象
	return(
		<>
			<h2>当前时间</h2>
			<p>{date}</p>
		</>
	);
}
*自定义hooks,封装重复使用的代码,可以抽离出成一个模块,在多个场景下使用,提高代码的复用性

#下一篇我们来讨论一下useCallback+useMemo+memo性能优化的场景

React进阶用法和hooks

1.lazy+Suspense懒加载的使用

3.useCallback+useMemo+memo性能优化

4.useReducer+useContext+createContext的使用、模拟redux合并reducer

5.useRef,useImperativeHandle和forwardRef的结合使用以及useLayoutEffect、useDebugValue的简单使用

  • 2
    点赞
  • 1
    评论
  • 8
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值