React基础

目录

一、开发环境搭建

当前主流方案是使用Vite脚手架:

bash 复制代码
npm create vite@latest 项目名 --template=react-ts

二、状态

1.状态驱动

传统开发依靠JavaScript+Ajax定位DOM元素并绑定事件,依靠事件驱动页面变化

React、Vue属于状态驱动,根据状态的变化实时更新页面,封装了事件驱动的过程,只关注页面结果。

typescript 复制代码
// 其中,在JavaScript中编写的HTML在编译阶段会被编译成JavaScript:
<h1 className="title">Hello World</h1>
// 实际上会被编译成:
React.createElement('h1', {className: 'title'}, 'Hello World');

状态驱动 即根据参数的值返回不同的HTML代码块,如果要基于某个参数的状态实时更新页面必须要使用 useState(0)定义参数:函数传入初始值和格式,返回状态变量和状态更新函数。

状态更新函数不仅会更新变量,还会触发该组件的一次重新渲染。由于状态变量具有不可变性,因此状态更新函数更新变量的原理是将新的状态变量赋值给引用。

javascript 复制代码
export function App() {
  // 状态
  const [count, setCount] = useState(0)
  // 视图
  return <div onClick={()=>setCount(count+1)}>{count}</div>
}

而以下方式参数变化不会引起页面变化:

typescript 复制代码
export function App() {
  // 状态
  let count = 0
  // 视图
  return <div onClick={()=>count+1}>{count}</div>
}

2.列表渲染

typescript 复制代码
import { useState } from 'react'

interface User {
  id: string
  name: string
}

export const ListDemo = () => {
  const [userId, setUserId] = useState('')
  const [userName, setUserName] = useState('')
  const [userList, setUserList] = useState<User[]>([])

  const addUser = () => {
    if (!userId || !userName) return
	// ...userList将旧数组数据取出。并追加一条新用户数据,用新数组更新状态变量
    setUserList([...userList, { id: userId, name: userName }])
    setUserId('')
    setUserName('')
  }

  return (
    <div>
      <input
        value={userId}
        onChange={(event) => setUserId(event.target.value)}
      />
      <input
        value={userName}
        onChange={(event) => setUserName(event.target.value)}
      />
      <button onClick={addUser}>+</button>

      <ul>
        {userList.map((item) => (
          <li}>{item.id} - {item.name}</li>
        ))}
      </ul>
    </div>
  )
}

三、参数

1.组件开发

组件开发即解耦页面为多个不同功能的组件,便于复用。

组件定义规范如下:

  1. 组件参数 一般用接口定义,参数可以是变量、函数。
  2. 使用export 将子组件暴露出去,其他文件可以通过import导入。
  3. 组件返回值是HTML代码块,可以根据参数渲染不同内容。
typescript 复制代码
import { useState } from "react"

interface HelloWorldProps{
    title: string,
    render?: ()=> React.ReactNode
}


export const HelloWorld = (props: HelloWorldProps) =>{
    const {title, render} = props;
    const [count, setCount] = useState(0);

    return <div>
        {title} <br/>
        {count} <button onClick={()=>{setCount(count+1)}}>+</button> 
        {render?.()}
    </div>
}

2.父组件向子组件传参

父组件通过组件属性向子组件传递参数,子组件使用函数形参捕获。

typescript 复制代码
import './App.css'
import { HelloWorld } from './components/HelloWorld/index'

export function App() {
  return <HelloWorld title='这是父组件向子组件传递参数' render= {()=>{return <div>这是父组件向子组件传递的函数</div>}}/>
}
typescript 复制代码
import { useState } from "react"

interface HelloWorldProps{
    title: string,
    render?: ()=> React.ReactNode
}

export const HelloWorld = (props: HelloWorldProps) =>{
    const {title, render} = props;

    return <div>
        {title} <br/>
        {render?.()}
    </div>
}

3.子组件向父组件传参

父组件通过组件属性向子组件传递由父组件编写的回调函数,子组件调用父组件的回调函数并传入参数,父组件就能通过函数体拿到子组件传入的参数。

typescript 复制代码
export function App() {
  const [num, setNum] = useState(0);
  return <div>
    <HelloWorld handle={(msg: number)=>{setNum(msg)}}/>
    <div>子组件向父组件传来的值:{num}</div>    
  </div>
}
typescript 复制代码
import { useState } from "react"

interface HelloWorldProps{
    handle?: (count: number)=> void
}

export const HelloWorld = (props: HelloWorldProps) =>{
    const {handle} = props
    const [count, setCount] = useState(0);

    return <div>
        {count} <button onClick={()=>{setCount(count+1); handle?.(count+1)}}>+</button> 
    </div>
}

四、副作用Hooks

Hook赋予组件能使用 state 状态、生命周期的能力,将静态组件动态化。

1.useState()

useState(0)用于维护状态变量,通过状态更新函数更新变量会触发该组件的一次重新渲染

javascript 复制代码
export function App() {
  // 状态
  const [count, setCount] = useState(0)
  // 视图
  return <div onClick={()=>setCount(count+1)}>{count}</div>
}

2.useEffect()

useEffect()用于监听状态变量的变化,当状态变量发生变化时执行函数体:

typescript 复制代码
import './App.css'
import { useEffect, useState } from 'react'

export function App() {
  // 状态
  const [count, setCount] = useState(0)
  //副作用
  useEffect(()=>{
    console.log({count})
  }, [count])
  // 视图
  return <div onClick={()=>setCount(count+1)}>{count}</div>
}
  • useEffect(()=>{},[prop]),状态变量发生变化时执行
  • useEffect(()=>{}),组件发生变化后执行
  • useEffect(()=>{},[]),仅组件挂载阶段执行

3.useRef()

useRef()用于获取DOM和缓存变量。

typescript 复制代码
import './App.css'
import { useRef } from 'react'

export function App() {
  // div对象
  const divRef = useRef<HTMLDivElement>(null)
  return <div ref={divRef}></div>
}

4.useActionState()

useActionState()用来获取表单提交状态和返回值。

typescript 复制代码
import { useActionState } from "react"

export const FormDemo = () => {
  const handleSubmit = async (formData: FormData) => {
    const name = formData.get("name")
    console.log({name})
    await api.post("/user", {name})   
    
    return {}
  }

  const [state, actions, pending] = useActionState(handleSubmit, null)
  console.log("当前提交状态和返回值", state)

  return (
    <form action={actions}>
      <input type="text" name="name" />
      <button type="submit">提交</button>
    </form>
  )
}
相关推荐
IT_陈寒1 小时前
Vue的动态组件坑了我整整一天!
前端·人工智能·后端
恋猫de小郭1 小时前
Flutter 最好的 AI 自动化测试工具:Patrol
android·前端·flutter
Cobyte1 小时前
AI 的个人便签纸:Claude Code 的 TodoWrite 模式
前端·后端·aigc
风兮雨露1 小时前
Java 从入门到精通,前端资料
java·开发语言·前端
ZC跨境爬虫1 小时前
跟着 MDN 学CSS day_43:CSS布局挑战——从浮动到弹性盒与栅格的综合实践
前端·css·ui·html·tensorflow
Qres8212 小时前
Hexo博客本地配置
前端·博客·hexo
Bigger2 小时前
GitLab-Runner + AI 代码审查服务 + 远程大模型 全套部署运维实战
前端·ci/cd·ai编程
_xaboy2 小时前
开源AI表单设计器 FcDesigner v3.5 版本发布!
前端·vue.js·低代码·开源·表单
爱讲故事的2 小时前
操作系统第三讲:Context Switch —— 用户态如何安全地进入内核态?
前端·javascript·安全