React+TS学习和使用(二)

开启学习react+ts,本篇主要是react函数式组件必备Hook,结合TS一起了解。

一、Hooks

1、useState

App.tsx 中使用 useState 定义数据,以及修改数据的方法,并传递给 Comp.tsx 子组件:

const [num, setNum] = useState(0);

<Comp1 num={num} />
   

子组件接收:

import React from 'react'

const Comp1: React.FC = function (props) {
    return (
        <>
            <h3>{props.num}</h3>
            <button>累加</button>
        </>
    )
}
export default Comp1;
    

很明显,这么接收直接就报错。因为TS强制要求必须指定传参的字段及其类型,因此应当改为:

import React from 'react'

const Comp1: React.FC = function (props: {num: number}) {
    return (
        <>
            <h3>{props.num}</h3>
            <button>累加</button>
        </>
    )
}
export default Comp1;
    

而实际上这是TS中接口的简化写法,完整点应该写为:

import React from 'react'

interface IProps {
    num: number;
}

// 使用IProps接口定义字段类型
const Comp1: React.FC<IProps> = function (props) {
    return (
        <>
            <h3>{props.num}</h3>
            <button>累加</button>
        </>
    )
}

export default Comp1;
    
A. 事件直接父传子使用

目前 setNum 依然处于定义了但未使用的状态,因此ESlint又会一直给出提示,因此我们可以把这个累加的效果实现:

// 父组件:
<Comp1 num={num} setNum={setNum} />

// 子组件
interface IProps {
    num: number;
    // 设定setNum为any
    setNum: any
}

<button onClick={()=>props.setNum(props.num+1)}>累加</button>
    

注意:

这里虽然设置为any可以实现累加,但不建议这么操作。

因此,真正的做法:

import React from 'react'

interface IProps {
    num: number;
    setNum: (num:number)=>void;
}

// 使用IProps接口定义字段类型
const Comp1: React.FC<IProps> = function(props) {
    return (
        <>
            <h3>{props.num}</h3>
            <button onClick={()=>props.setNum(props.num+1)}>累加</button>
        </>
    )
}

export default Comp1;
    
B. 事件用子传父的做法
* 父组件
import React, {useState, useCallback} from 'react'
import Comp1 from 'components/Comp1'

const App: React.FC = () => {
    const [num, setNum] = useState(0)

	const toSetNum = (value: number) => setNum(value)

    return (
        <>
            <h2>你好世界</h2>
            <Comp1 num={num} toSetNum={()=>toSetNum} />
        </>
    )
}

export default App;
    

setNum(newValue):代表直接用新值替换初始值

setNum(preValue => newValue):代表用新值替换旧值

* 子组件
import React from 'react'

interface IProps {
    num: number;
    toSetNum: (num:number)=>void;
}

// 使用IProps接口定义字段类型
const Comp1: React.FC<IProps> = function(props) {
    return (
        <>
            <h3>{props.num}</h3>
            <button onClick={()=>props.toSetNum(props.num+1)}>累加</button>
        </>
    )
}

export default Comp1;
    

2、useEffect

React的Class Component中有 componentDidMountcomponentDidUpdatecomponentWillUnmount,但Function Component并没有。

A、componentDidMount
useEffect(()=>{
  console.log('componentDidMount')
}, [])	// 空数组表示不检测任何数据变化

    
B、comopnentDidUpdate
useEffect(()=>{
  console.log('comopnentDidUpdate')
}, [num])	// 如果数组中包含了所有页面存在的字段,也可以直接不写
   

如果监听路由的变化:

// 需要先安装路由,而且是react-router-dom@v6.x
useEffect(()=>{
  console.log('路由变化')
}, [location.pathname])

    
C、componentWillUnmount
useEffect(()=>{
  return ()=>{
    // callback中的return代表组件销毁时触发的事件
  }
}, [])
    

3、memo、useMemo与useCallback

在Function Component中,也不再区分mountupdate两个状态,这意味着函数组件的每一次调用都会执行内部的所有逻辑,就带来了非常大的性能损耗。useMemouseCallback都是解决上述性能问题的。

来看下面这段代码:

import React, { useState, useMemo, useCallback } from "react";

const Sub = () => {
  console.log("Sub被渲染了");	// 这行代码在父组件App2更新时,它也被迫一直更新
  return <h3>Sub组件</h3>;
};

export default function App2() {
  const [num, setNum] = useState<number>(0);

  const changeNum = () => setNum(num + 1)

  return (
    <div>
      <h2>num的值:{num}</h2>
      <button onClick={changeNum}>累加num</button>
      <Sub />
    </div>
  );
}

以上代码中可以测试出来,Sub组件的 console.log 在App2组件更新时,一直被迫触发,这就是典型的性能浪费。

A. memo

使用memo这个hook可以解决这一问题:

import React, { useState, memo } from "react";

// Sub组件需要被memo包裹
const Sub = memo(() => {
    console.log("Sub被渲染了");
    return <h3>Sub组件</h3>;
  });

export default function App2() {
  const [num, setNum] = useState<number>(0);
    
  const changeNum = () => setNum(num + 1)

  return (
    <div>
      <h2>num的值:{num}</h2>
      <button onClick={changeNum}>累加num</button>
      <Sub />
    </div>
  );
}
    

memo可以缓存组件,当组件的内容不受修改时,可以不更新该组件。

B. useCallback

但我们希望num的变化不造成Sub组件的更新:

import React, { useState, memo, useCallback } from "react";

interface ISubProps {
  changeNum: () => void;
}

// Sub组件需要被memo包裹
const Sub = memo((props: ISubProps) => {
  console.log("Sub被渲染了");
  return (
    <>
      <button onClick={props.changeNum}>累加num</button>
      <h3>Sub组件</h3>
    </>
  );
});

export default function App2() {
  const [num, setNum] = useState<number>(0);

  // 将这个changeNum函数使用useCallback包裹一次
  const changeNum = useCallback(()=>{
      setNum((num)=>num+1)
  }, [])

  return (
    <div>
      <h2>num的值:{num}</h2>
      <Sub changeNum={changeNum} />
    </div>
  );
}

C. useMemo

useMemo与useCallback大致相同,只是useMemo需要在回调函数中再返回一个函数,我们称之为高阶函数:

import React, { useState, memo, useMemo } from "react";

interface ISubProps {
  changeNum: () => void;
}

// Sub组件需要被memo包裹
const Sub = memo((props: ISubProps) => {
  console.log("Sub被渲染了");
  return (
    <>
      <button onClick={props.changeNum}>累加num</button>
      <h3>Sub组件</h3>
    </>
  );
});

export default function App2() {
  const [num, setNum] = useState<number>(0);

  // 将这个changeNum函数改为useMemo
  const changeNum = useMemo(() => {
    return () => setNum((num) => num + 1);
  }, []);

  return (
    <div>
      <h2>num的值:{num}</h2>
      <Sub changeNum={changeNum} />
    </div>
  );
}
  

4、自定义hook

React中的hook允许我们自定义,来尝试一个简单的:

自定义一个hook,将所有的小写字母改大写。

import React from 'react'

const word = "Hello World";

function useBigWord(w: string){
    return w.toUpperCase();
}

const App3 = () => {
    const bigWord = useBigWord(word)
    return (
        <div>
            <h3>小写:{word}</h3>
            <h3>大写:{bigWord}</h3>
        </div>
    )
}

export default App3
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
React+TypeScript脚手架是一种用于创建React项目的工具。通过使用create-react-app脚手架,可以快速搭建一个React项目,并且使用TypeScript作为项目的开发语言。\[1\] 使用步骤如下: 1. 首先,需要安装create-react-app工具。可以通过以下命令进行安装: ``` npm i create-react-app -g ``` 或者 ``` yarn add create-react-app -g ``` 2. 然后,使用create-react-app命令来创建一个React+TypeScript项目。命令的格式如下: ``` npx create-react-app <项目名> --template typescript ``` 注意,项目名不要使用中文,否则会报错。\[2\] 3. 创建完成后,可以在VSCode中打开项目。可以看到项目中已经生成了React项目的雏形,组件的后缀为.tsx,这说明成功创建了React+TypeScript项目。\[1\] 4. 在项目中,可以根据需要进行配置。通常,可以在App组件中进行配置,例如引入所需的组件、样式和路由等。\[3\] 希望以上信息对你有帮助!如果还有其他问题,请随时提问。 #### 引用[.reference_title] - *1* *3* [react+ts搭建](https://blog.csdn.net/m0_56540662/article/details/124267829)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [React+ts搭建脚手架](https://blog.csdn.net/weixin_51612593/article/details/120249135)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨小凹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值