• React ts学习重点(组件状态,Hooks,路由)


    项目创建

    npx create-react-app@latest project-name --template typescript
    
    • 1

    组件状态定义

    //定义State规定state内部有状态数据的类型
    interface State {
      areas: IArea[]
      albums: IAlbum[]
      currentArea: number
    }
    
    //两个参数 第一个是Props(从父组件传入的数据类型),第二个参数是当前页面有状态数据的类型
    class App extends React.Component<any, State> {
      
      //对有状态数据进行初始化
      state: State = {
        areas: [],
        albums: [],
        currentArea: 1
      }
      
      //异步请求tab标签和专辑信息
      async getData() {
        let getareas = await request.get<IArea[]>('data/areas.json')
        let getalbums = await request.get<IAlbum[]>('data/albums.json')
        this.setState({
          areas: getareas,
          albums: getalbums,
          currentArea: 1,
        })
      }
      //执行请求的方法要写在这个方法里面
      componentDidMount(): void {
        this.getData()
      }
    
      render() {
        const {areas,currentArea} = this.state
        return <div className="app">
          <Header />
          <main>
            <AreasTab
              areas={areas}
              currentId={currentArea}
              tabChange={this.tabChange} />
            <section className="list">
              {this.currentAlbums().map((album) => {
                return <AlbumItem
                  key={album.id}
                  album={album}
                  deleteAlbum={this.deleteAlbum}
                />
              })
              }
            </section>
          </main>
        </div >
      }
    }
    
    ReactDOM.render(<App />, document.getElementById('app'))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    props设置默认值

    type ButtonType = 'default' | 'primary'
    interface Props {
      type?: ButtonType
      onClick?: () => void
    }
    export default class Button extends React.Component<Props> {
      static defaultProps = {
        type:'default'
      }
      render() {
        const {type,onClick} = this.props
        let btnclassname = `button button-${type}`
        return <button className = {btnclassname}>
          {this.props.children}
        </button>
      }
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    路由

    安装插件(v6版本)

    npm add react-router-dom@6
    
    • 1

    核心组件

    BrowerRouter
    在这里插入图片描述
    Link(还有NavLink)
    在这里插入图片描述
    Routes
    在这里插入图片描述
    Route
    在这里插入图片描述

    一级路由

    点击首页和关于分别导航到Home和About页面
    在这里插入图片描述

    二级路由

    使用<Outlet/>指定二级路由出口,相当于vue中的router-view
    在一级路由下的某个页面再嵌套几个路由
    index代表默认路由

    import * as React from 'react'
    import { BrowserRouter, Route, Routes } from 'react-router-dom'
    import Article from '../Article'
    import Detail from '../Detail'
    import Main from '../Main'
    import Consult from '../Consult'
    
    export default class App extends React.Component {
    
      render() {
        return (
          <BrowserRouter>
               //一级路由
                <Routes>
                    <Route path='/' element={<Main/>} >
                      //二级路由(index代表默认路由),再Main页面下又有两个页面
                      <Route index element={<Article/>}/>
                      <Route path='article' element={<Consult/>}/>
                    </Route>
                    <Route path='/detail' element={<Detail/>} />
                </Routes>
          </BrowserRouter>
        )
      }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    Main页面下

    import React from 'react'
    import { Outlet } from 'react-router-dom'
    import './style.css'
    export default class Main extends React.Component {
        render(): React.ReactNode {
            return <React.Fragment>
                <div className="page">
                    <header className="top">
                       <nav className="tabs">
    			         <ul>
    			           <NavLink to='/'>好文精选</NavLink>
    			           <NavLink to='/article'>热门资讯</NavLink>
    			         </ul>
                       </nav>
                    </header>
                    //指定二级路由出口,相当于vue中的router-view
                    <Outlet />
                </div>
            </React.Fragment>
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    路由转跳

    1. 导入useNavigate钩子函数

      import { useNavigate } from 'react-router-dom'
      
      • 1
    2. 执行钩子函数得到转跳函数

      const navigate = useNavigate()
      
      • 1
    3. 执行转跳函数完成转跳

      navigate('/about')
      
      • 1

      如果转跳时不想添加历史,可以额外添加replace为true

      navigate('/about',{replace:true})
      
      • 1

    携带参数转跳

    searchParams传参

    导包

    import { useSearchParams } from 'react-router-dom'
    
    • 1

    传参

    参数为静态的话
    navigate('/detail?id=1001')
    参数为动态的话
    navigate(`/detail?id=${id}`)
    
    • 1
    • 2
    • 3
    • 4

    取参数

    let [params] = useSearchParams()
    let id = params.get('id')
    
    • 1
    • 2

    在这里插入图片描述
    得到的链接路径为
    在这里插入图片描述

    params传参

    这种方法传参在写path时需要配合id=/:id

    导包

    import { useNavigate, useParams } from 'react-router-dom'
    
    • 1

    传参

    参数为静态的话
    navigate('/detail/id=1001')
    参数为动态的话
    navigate(`/detail/id=${id}`)
    
    • 1
    • 2
    • 3
    • 4

    取参数

    let params = useParams()
    let id = params.id
    
    • 1
    • 2

    在这里插入图片描述
    得到的链接路径为:
    在这里插入图片描述

    import React, { useEffect, useState } from 'react'
    import { useNavigate } from 'react-router-dom'
    
    
    
    export default function Article() {
    
        const navigate = useNavigate()
       
        const toDetail = (id: String) => {
            navigate(`/detail?id=${id}`)
        }
        return <React.Fragment>
       
        </main>
    </React.Fragment>
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    返回上一级

    navigate(-1)

    import { useNavigate } from 'react-router-dom'
    function Detail() {
    
        const navigate = useNavigate()
        const goBack = () => {
            navigate(-1)
        }
    
        return <React.Fragment>
        </React.Fragment>
    }
    
    export default Detail
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    404路由配置

    当所有路径都不匹配时转跳到添加 * 的路由

    <Route path='*' element={<NoFound/>}><Route/>
    
    • 1

    Hooks

    useState

    为函数组件提供状态

    import React from 'react'
    import { useEffect, useState } from 'react'
    
    function Detail() {
    
       //第一个是属性,第二个是改变属性值的方法,number对属性类型进行限定,0表示初始值
        const [count, setCount] = useState<number>(0)
    
        return <React.Fragment>
        return (
        <button onClick={() => { setCount(count + 1) }}>{count}</button>
      )
        </React.Fragment>
    }
    
    export default Detail
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    如果参数的初始值需要计算的话,可以写成如下形式

     const [count, setCount] = useState<number>(() => {
        return 计算后的值(这个回调函数只会在组件初始化时执行一次) 
        }
     )
    
    • 1
    • 2
    • 3
    • 4
    useEffect

    副作用函数,副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
    常见的副作用

    • 数据请求 ajax发送
    • . 手动修改dom
    • localstorage操作
    1. 不添加依赖

    组件首次渲染执行一次,以及不管是哪个状态更改引起组件更新时都会重新执行

    1. 组件初始渲染
    2. 组件更新 (不管是哪个状态引起的更新)
    	import { useEffect, useState } from 'react'
    	
    	function App() {
    	  const [count, setCount] = useState(0)
    	  useEffect(()=>{
    	    // dom操作
    	    document.title = `当前已点击了${count}`
    	  })
    	  return (
    	    <button onClick={() => { setCount(count + 1) }}>{count}</button>
    	  )
    	}
    	
    	export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 添加空数组

    组件只在首次渲染时执行一次

    import React, { useEffect,useState } from 'react'
    import { news } from '../../services/api'
    import { IArticle } from '../../type/types'
    
    function Consult() {
    
        const [goodmessagelist, setGoodmeaasgelist] = useState<IArticle[]>([])
        useEffect(() => {
            const getData = async () => {
                let res = await news()
                setGoodmeaasgelist(res.rows)
            }
            getData()
        }, [])
        return <React.Fragment>
        </React.Fragment>
    }
    
    export default Consult
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1. 添加特定依赖项

    副作用函数在首次渲染时执行,在依赖项发生变化时重新执行

    import React from 'react'
    import { useEffect, useState } from 'react'
    import { useNavigate, useSearchParams } from 'react-router-dom'
    import { detail } from '../../services/api'
    import { IArticle } from '../../type/types'
    import './style.css'
    
    function Detail() {
    
        const [aritcle, setAritcle] = useState<IArticle>()
    
        let [params] = useSearchParams()
    
        useEffect(() => {
            const getData = async () => {
                let id = params.get('id')
                if (id !== null) {
                    let res = await detail(id)
                    console.log(res)
                    setAritcle(res.data)
                }
            }
            getData()
        }, [params])
    
        return <React.Fragment>
        </React.Fragment>
    }
    
    export default Detail
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    useRef

    在函数组件中获取真实的dom元素对象或者是组件对象

    1. 导入 useRef 函数
    2. 执行 useRef 函数并传入null,返回值为一个对象 内部有一个current属性存放拿到的dom对象(组件实例)
    3. 通过ref 绑定 要获取的元素或者组件

    获取dom

    import { useEffect, useRef } from 'react'
    function App() {  
        const h1Ref = useRef(null)  
        useEffect(() => {    
            console.log(h1Ref)  
        },[])  
        return (    
            <div>      
                <h1 ref={ h1Ref }>this is h1</h1>    
            </div>  
        )
    }
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    获取组件实例

    函数组件由于没有实例,不能使用ref获取,如果想获取组件实例,必须是类组件

    Foo.js

    class Foo extends React.Component {  
        sayHi = () => {    
            console.log('say hi')  
        }  
        render(){    
            return <div>Foo</div>  
        }
    }
        
    export default Foo
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    App.js

    import { useEffect, useRef } from 'react'
    import Foo from './Foo'
    function App() {  
        const h1Foo = useRef(null)  
        useEffect(() => {    
            console.log(h1Foo)  
        }, [])  
        return (    
            <div> <Foo ref={ h1Foo } /></div>  
        )
    }
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    useContext
    1. 使用createContext 创建Context对象
    2. 在顶层组件通过Provider 提供数据
    3. 在底层组件通过useContext函数获取数据

    代码实现

    import { createContext, useContext } from 'react'
    // 创建Context对象
    const Context = createContext()
    
    function Foo() {  
        return <div>Foo <Bar/></div>
    }
    
    function Bar() {  
        // 底层组件通过useContext函数获取数据  
        const name = useContext(Context)  
        return <div>Bar {name}</div>
    }
    
    function App() {  
        return (    
            // 顶层组件通过Provider 提供数据    
            <Context.Provider value={'this is name'}>     
                <div><Foo/></div>    
            </Context.Provider>  
        )
    }
    
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    CSS module

    参考:react中使用css module
    主要注意三点:

    1. css文件名前加.modue
    2. 引入时import style from …
    3. 使用时通过style.调用
      请添加图片描述
  • 相关阅读:
    Java代理简介
    亚马逊产品召回后如何重新发布商品?儿童睡衣,婴儿沐浴座椅,不锈钢儿童水杯被召回
    Fair下发产物-布局DSL生成原理
    axios在vue里简单的封装使用
    概念:云计算
    【LaTex】 - 对齐符号&的用法,换行符\\的用法,Misplaced &错误怎么解决
    Ubuntu20.4搭建基于iRedMail的邮件服务器
    Blocking waiting for file lock on the registry index 问题解决
    嵌入式杂记 -- MCU的大小端模式
    C++语言实现网络爬虫详细代码
  • 原文地址:https://blog.csdn.net/m0_46527751/article/details/125629064