首页 > 其他分享 >react速成指南

react速成指南

时间:2024-07-16 20:55:14浏览次数:8  
标签:指南 function const useMemo App 速成 react default return

React18速成–适合有vue基础的同学

目录

前言

该博客为本人的学习记录,并不是一篇教程,请结合b站视频食用:

【30分钟学会React18核心语法 可能是你学会React最好的机会 前端开发必会框架 无废话精品视频】https://www.bilibili.com/video/BV1pF411m7wV?vd_source=0d0d6b12377aa593bc3a34f0884de98a

有vue基础的同学建议看完视频入门后去看官方文档学习
若是没有vue基础的同学可以去看长教学视频学习(本视频可看可不看)
ps:代码看不懂的话可以下载vscode插件通义千问等AI插件,一键注释

脚手架创建react项目

npx create-react-app 项目名字

jsx重点知识

1.在jsx语法中html直接内嵌在函数中并通过return返回
2.jsx只能有一个根元素(整合成一个盒子)
// @ts-nocheck
import logo from './logo.svg';
import './App.css';

function App() {
  return (
  <>
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
      </header>
    </div>
    <div></div>
   </>
  );
}

export default App;
3.插值

条件渲染

function App(){
  const divTitle = '标签标题'
  const flag = true;
  let divContent = ''
  if(flag){
    divContent = <span>flag为true</span>//不需要为字符串形式
  }else{
    divContent = <p>flage为false</p>
  }
  return(
    <div title={divTitle}>{divContent}</div>
  )
}

export default App;

列表渲染

function App(){
  const list = [
    {id:1,name:'xiaowu'},
    {id:2,name:'xiaoli'},
    {id:3,name:'xiaohua'}
  ] 
  const listContent = list.map(item => (
    <li key={item.id}>{item.name}</li>
  )) 
  return(
    <ul>{listContent}</ul>
  )
}

export default App;

4.事件操作

基础操作

import React, { Fragment, useState } from "react";
function App(){
  //       读        改      (名字可以自己定义)
  const [content, setContent] = useState('默认内容')
  function handleClick(){
    setContent('新内容')
  }
  return(
    <>
      <div>{content}</div>
      <button onClick={handleClick}>按钮</button>
    </>
  )
}

export default App;

对象操作

import React, { Fragment, useState } from "react";
function App(){
  const [data, setData] = useState({
    title:'默认标题',
    content:'默认内容'
  })
  function handleClick(){
    setData({
      ...data,
      title:'新标题'
    })
  }
  return(
    <>
      <div title={data.title}>{data.content}</div>
      <button onClick={handleClick}>按钮</button>
    </>
  )
}

export default App;

数组操作

import React, { Fragment, useState } from "react";
function App(){
  const [data, setData] = useState([
    {id:1,name:'xiaowu'},
    {id:2,name:'xiaoli'},
    {id:3,name:'xiaohua'}
  ])
  const listData = data.map(item=>(
    <li key={item.id}>{item.name}</li>
  ))
  let td=3;
  function handleClick(){
    setData([
      ...data,
      {id:++td,name:'xiaohuamao'}
    ])
  }
  return(
    <>
      <ul>{listData}</ul>
      <button onClick={handleClick}>按钮</button>
    </>
  )
}

export default App;


React18组件通信与插槽

1.为dom组件设置Props

在react中给dom设置class时防止与js中class重复:采用className

// @ts-nocheck
import image from './logo.svg'
function App(){
  return(
   <div>
    <img
      src={image}
      alt=""
      className=""
    />
   </div>
  )
}
export default App;

以变量形式赋值style

// @ts-nocheck
import image from './logo.svg'
function App(){
  const imgStyleObj={
    with:100,
    height:100,
    backgroundColor:'grep'
  }

  return(
   <div>
    <img
      src={image}
      alt=""
      className=""
      style={imgStyleObj}
    />
   </div>
  )
}
export default App;
 

通过jsx展开语法(与es6中展开运算符不同,不要混淆)

// @ts-nocheck
import image from './logo.svg'
function App(){
  const imgStyleObj={
    className:'small',
    with:100,
    height:100,
    backgroundColor:'grep'
  }

  return(
   <div>
    <img
      src={image}
      alt=""
      {...imgStyleObj}
    />
   </div>
  )
}
export default App;
 
2.react组件的Props

react简单函数式组件

function Article({title,content,active}){
  return(
    <div>
      <h2>{title}</h2>
      <p>{content}</p>
      <p>状态:{active ? '显示中' : '已隐藏'}</p>
    </div>
  )
}
export default function App() {
  return(
    <>
      <Article
        title="1"
        content="1"
        active
      />
    </>
  )
}

嵌套式传值

function Detail ({content,active}){
  return(
    <>
      <p>{content}</p>
      <p>状态:{active ? '显示中' : '已隐藏'}</p>
    </>
  )
}
function Article({title,detailData}){
  return(
    <div>
      <h2>{title}</h2>
      <Detail {...detailData}/>
    </div>
  )
}
export default function App() {
  const ArticleData = {
    title:'标题1',
    detailData:{
      content:'内容1',
      active:true
    }
  }
  return(
    <>
      <Article
        {...ArticleData}
      />
    </>
  )
}

react中插槽传值

function List ({children}) {
  return (
    <ul>
      {children}
    </ul>
  )
}
export default function App() {
  return(
    <>
      <list>
        <li></li>
        <li></li>
        <li></li>
      </list>
    </>
  )
}

react父子传值

// @ts-nocheck
import {useState} from "react"

function Detail({onActive}){
  const [status,setStatus] = useState(false)
  function handleClick(){
    setStatus(!status)
    onActive(status)
  }
  return (
    <div>
      <button onClick={handleClick}>按钮</button>
      <p style={{
        display:status ? 'block' : 'none'
      }}>Detail的内容</p>
    </div>
  )
}
export default function App() {
  function handleActive(status){
    console.log(status)
  }
  return(
    <>
      <Detail
        onActive={handleActive}
      />
    </>
  )
}

React Hooks

1.reducer
// @ts-nocheck
import {useReducer, useState} from "react"

function countReducer(state,action){
  switch(action.type){
    case "increment":
      return state + 1
    case "decrement:":
      return state - 1
    default:
      throw new Error()
  }
}
export default function App() {
  const [state,dispatch] = useReducer(countReducer,0)
  const handleIncrement = () => dispatch({type:"increment"})
  const handleDecrement = () => dispatch({type:"decrement"})
  return(
    <div style={{padding:10}}>
      <button onClick={handleIncrement}>-</button>
      <span>{count}</span>
      <button onClick={handleDecrement}>+</button>
    </div>
  )
}
2.useRef

记录修改前的状态

记录上一次的值

// @ts-nocheck
import {useReducer, useState} from "react"

export default function App() {
  const [count,setCount] = useState(0)
  const prevCount = useRef()

  function handleClick(){
    prevCount.current = count
    setCount(count + 1)
  }
  return(
    <div>
      <p>最新的count:{count}</p>
      <p>上次的count:{prevCount.current}</p>
      <button onClick={handleClick}>增大count</button>
    </div>
  )
}

通过ref实现子组件功能访问

// @ts-nocheck
import { forwardRef, useImperativeHandle, useReducer, useState } from "react"

/**
 * 定义一个名为Child的组件,使用forwardRef创建一个引用。
 * 这个组件通过引用来提供一个自定义的focus方法。
 * 
 * @param {Object} props - 组件的props,不包含特定的属性。
 * @param {Object} ref - 一个用于获取组件实例的引用。
 * @returns 返回一个简单的div元素,这个div通过ref暴露了focus方法。
 */
const Child = forwardRef((props, ref) => {
  // 使用useImperativeHandle钩子来定义ref的行为。
  useImperativeHandle(ref, () => ({
    focus: () => {
      console.log('focus')
    }
  }))
  return (
    <div>子组件</div>
  )
})

/**
 * App组件是应用程序的主入口点。
 * 它使用了一个ref来直接访问Child组件的实例,并且提供了一个按钮来触发Child组件的focus方法。
 * 
 * @returns 返回一个包含Child组件和一个按钮的div元素。
 */
export default function App() {
  // 创建一个ref来保存Child组件的实例。
  const childRef = useRef()
  
  /**
   * 点击按钮时调用的函数,用于触发Child组件的focus方法。
   */
  function handleClick() {
    childRef.current.focus()
  }
  
  return (
    <div>
      <Child ref={childRef} />
      <button onClick={handleClick}>聚焦</button>
    </div>
  )
}
3.useEffect
// @ts-nocheck
import { useState,useEffect } from "react"

export default function App() {
  const [count, setCount] = useState(0)
  const handleIncrement = () => {
    setCount(count + 1)
  }
  const handleDecrement = () => {
    setCount(count - 1)
  }
  useEffect(() => {
    console.log('useEffect')
  },[count]);
  return (
    <div style={{padding:10}}>
      <button onClick={handleIncrement}>-</button>
      <span>{count}</span>
      <button onClick={handleDecrement}>+</button>
    </div>
  )
}
4.useMemo

如何使用useMemo

  1. 确定计算结果: 首先,识别出你的组件中哪些计算是昂贵的,并且在每次渲染时都不需要重新计算,除非某些特定的状态或属性发生了改变。
  2. 创建记忆化的值: 使用useMemo来包装这个计算,将计算逻辑放在useMemo的第一个参数的函数中,这个函数被称为工厂函数。
  3. 指定依赖项: 在useMemo的第二个参数中,提供一个依赖项数组。这个数组应该包含所有影响计算结果的变量。如果依赖项数组中的任何值发生变化,useMemo将重新执行工厂函数。
  4. 使用记忆化的值: 在组件的其他部分使用useMemo返回的记忆化值,而不是直接调用计算函数。

假设你有一个组件,它需要根据用户的输入动态生成一个复杂的图表数据集。你可以使用useMemo来避免在每次渲染时都重新生成这个数据集。

import React, { useState, useMemo } from 'react';

function ChartDataGenerator() {
  const [inputValue, setInputValue] = useState(0);

  const complexChartData = useMemo(() => {
    // 这个函数模拟一个复杂的计算过程
    const data = Array.from({ length: inputValue }, (_, i) => Math.random());
    return data;
  }, [inputValue]);

  return (
    <div>
      <input type="number" value={inputValue} onChange={e => setInputValue(Number(e.target.value))} />
      <pre>{JSON.stringify(complexChartData, null, 2)}</pre>
    </div>
  );
}

在这个例子中,complexChartData只有在inputValue改变时才会重新计算。这可以显著提高组件的性能,特别是在complexChartData的生成是一个昂贵的操作时。

注意事项

  • useMemo主要用于避免不必要的计算,但它不应该被过度使用。在大多数情况下,React的虚拟DOM算法已经足够高效,不需要额外的优化。
  • 如果依赖项数组为空,useMemo将只在组件挂载时计算一次。
  • 如果依赖项数组中的某个值是引用类型(如对象或数组),即使其内部状态没有改变,只要引用本身改变了,useMemo也会重新计算。
  • 不要在useMemo的依赖项数组中包含函数或类实例,因为它们在每次渲染时都会创建新的引用,这会导致useMemo每次都重新执行。
5.useCallBack

与useMemo很像

区别:useCallBack作用于变量,useMemo作用于函数

一个例子说明区别:

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

function CounterApp() {
  const [counter, setCounter] = useState(0);

  // 使用 useCallback 缓存 函数 以避免在每次渲染时创建新的函数引用
  const incrementCounter = useCallback(() => {
    setCounter(counter + 1);
  }, [counter]);

  // 使用 useMemo 缓存计算结果( 变量 ),避免在每次渲染时重复计算
  const fibonacci = useMemo(() => {
    if (counter <= 1) return counter;
    return fibonacci(counter - 1) + fibonacci(counter - 2);
  }, [counter]);

  return (
    <div>
      <h1>Counter: {counter}</h1>
      <button onClick={incrementCounter}>Increment</button>
      <p>Fibonacci of {counter}: {fibonacci}</p>
    </div>
  );
}

export default CounterApp;
  1. useCallback 示例:

    在上面的例子中,incrementCounter 函数使用 useCallback 进行缓存。这意味着只要 counter 的值没有改变,incrementCounter 函数的引用就不会改变。这对于性能优化很重要,特别是在将函数作为 prop 传递给子组件时,可以避免不必要的子组件重新渲染。

  2. useMemo 示例:

    fibonacci 计算使用了 useMemo。由于斐波那契数列的计算可能是昂贵的操作,我们不想在每次组件渲染时都重新计算它,除非 counter 的值确实改变了。useMemo 确保了只有当依赖项 counter 发生变化时,计算才被执行,否则它将返回上一次计算的结果。

总结

  • useCallback 用于优化函数引用,避免在每次渲染时创建新的函数实例,这有助于减少不必要的子组件重新渲染。
  • useMemo 用于优化计算结果的缓存,避免在每次渲染时重复执行相同的计算,这有助于减少不必要的计算开销。

在上述示例中,useCallbackuseMemo 分别用于优化事件处理器和计算密集型操作,共同提高了应用的性能。

TodoList综合案例react18+ts

page.tsx

import AddTodo from '../components/AddTodo'
import TodoList from '../components/TodoList'
import TodoFilter from '@/components/TodoFilter'
import { useState } from 'react';
import { Todo } from '@/type';
export default function Home() {
  const [todos, setTodos] = useState<Todo[]>([]);
  const [filter, setFilter] = useState('all');
  //添加功能
  const addTodo = (text:string) => {
    const newTodo = {
      id:Date.now(),
      text,//在这
      completed:false
    }
    setTodos([...todos,newTodo])
  }
  //删除功能
  const deleteTodo = (id:number) => {
    setTodos(todos.filter(todos => todos.id !== id))
  }
  //切换功能
  const toggleTodo = (id:number) => {
    setTodos(todos.map(todo => {
      if(todo.id === id){
        return {
          ...todo,
          completed:!todo.completed
        }
      }
      return todo
    }))
  }
  //过滤功能
  const getFilteredTodos = () =>{
    switch(filter){
      case 'all':
        return todos
      case 'completed':
        return todos.filter(todo => todo.completed)
      case 'active':
        return todos.filter(todo => !todo.completed)
      default:
        return todos
    }
  }  
  return (
    <div>
      <h1>TodoList</h1>
      <AddTodo addTodo={addTodo}></AddTodo>
      <TodoList todos={getFilteredTodos()} deleteTodo={deleteTodo} toggleTodo={toggleTodo}></TodoList>
      <TodoFilter setFilter={setFilter}></TodoFilter>
    </div>
    
  )
}

type.ts
export interface Todo{
    id:number;
    text:string;
    completed:boolean;
}
AddTodo.tsx
import { useState } from "react"
interface AddTodoProps{
    addTodo: (text:string) => void
}
function AddTodo({addTodo}:AddTodoProps){
    const [text,setText] = useState('')
    const handleSubmit = (e:React.FormEvent<HTMLFormElement>) => {
        e.preventDefault()
        if(text.trim() === ''){
            return
        }
        addTodo(text)
        setText('')
    }
    return (
        <form>
            <input 
            type="text"
            value={text} 
            onChange={e => setText(e.target.value)} 
            />
            <button>新建事项</button>
        </form>
    )
   }
export default AddTodo
TodoItem.tsx
import { Todo } from "@/type"
interface TodoItemProps {
    todo:Todo;
    toggleTodo: (id:number) => void;
    deleteTodo: (id:number) => void;
}
function TodoItem({todo,toggleTodo,deleteTodo}:TodoItemProps){
    return(
        <li style={{textDecoration:todo.completed ? 'line-through' : 'none'}}>
            {todo.text}
            <button onClick={() => toggleTodo(todo.id)}>切换</button>
            <button onClick={() => deleteTodo(todo.id)}>删除</button>
        </li>
    )
}
export default TodoItem
TodoFilter.tsx
function TodoFilter ({setFilter}:any){
    return(
        <div>
            <button onClick={() => setFilter('all')}>All</button>
            <button onClick={() => setFilter('active')}>Active</button>
            <button onClick={()=>setFilter('completed')}>Completed</button>
        </div>
    )
}
export default TodoFilter
TodoList.tsx
import { Todo } from "../type";
import TodoItem from "./TodoItem";
interface TodoListProps {
  todos:Todo[]; 
  toggleTodo: (id:number) => void;
  deleteTodo: (id:number) => void;
}
function TodoList({todos,toggleTodo,deleteTodo}:TodoListProps) {
  return (
    <ul>
        {
            todos.map(todo => (
                <TodoItem key={todo.id} todo={todo} toggleTodo={toggleTodo} deleteTodo={deleteTodo}></TodoItem>
            ))
        }
    </ul>
  );
}
export default TodoList

标签:指南,function,const,useMemo,App,速成,react,default,return
From: https://blog.csdn.net/qq_74099184/article/details/140453648

相关文章

  • 快速上手 Caffeine:Java 缓存库初学者指南
    一、背景简介:Caffeine是一个高性能的Java缓存库,旨在为现代应用程序提供快速、高效的缓存解决方案。它由GoogleGuavaCache的创始人之一开发,具备基于时间的过期、基于大小的回收、异步加载、统计信息等多种特性。Caffeine的性能有多么强大呢?以下是官方给出的基准测试......
  • Go微服务开发指南
    在这篇深入探讨Go语言在微服务架构中的应用的文章中,我们介绍了选择Go构建微服务的优势、详细分析了主要的Go微服务框架,并探讨了服务发现与注册和API网关的实现及应用。关注TechLead,复旦博士,分享云服务领域全维度开发技术。拥有10+年互联网服务架构、AI产品研发经验、团队管理......
  • React+TS前台项目实战(三十)-- 首页构建之基于react-query和性能hook实现全页面数据渲染
    文章目录前言一、效果展示二、首页源码+详细注释说明+技术分析1.页面功能分析2.代码+详细注释总结前言前三篇文章详细介绍了首页的响应式布局,采用关注点分离进行模块拆解,现在只需按需引入模块,页面更加简洁,代码的维护性得到提升。今天将进入首页的收尾阶段,即完成......
  • vite react Typescript 构建一个移动端网页
    使用Vite、React和TypeScript来构建一个移动端网页是一个高效且现代的开发方式。Vite是一个构建工具和开发服务器,它利用原生ES模块导入来提供快速的冷启动和即时模块热更新(HMR)。React是用于构建用户界面的JavaScript库,而TypeScript是JavaScript的一个超集,它添......
  • 提升 Python 水平的高级指南
    Python是一种功能强大且灵活的编程语言,深受开发者喜爱。尽管Python易于学习,但要掌握其高级特性并将其运用自如,需要不断深入学习与实践。本文旨在帮助已经熟悉Python基础的开发者,探索更高级的Python技巧与最佳实践,提升编程水平。1.高级数据结构数据结构概述数据结......
  • 优化PHP开发流程:精选工具与配置指南,提升代码质量与效率
    本文由ChatMoney团队出品在PHP开发领域,选择正确的工具可以极大地提升开发效率和代码质量。集成开发环境(IDE)PHPStorm是一个强大的IDE,专为PHP开发设计。它提供了丰富的功能,如智能代码补全、代码分析、实时错误预防、重构工具、数据库工具和版本控制集成。安装与配置PHPSto......
  • 深入理解 React 的 useSyncExternalStore Hook
    深入理解React的useSyncExternalStoreHook大家好,今天我们来聊聊React18引入的一个新Hook:useSyncExternalStore。这个Hook主要用于与外部存储同步状态,特别是在需要确保状态一致性的场景下非常有用。本文将深入探讨这个Hook的使用场景、工作原理,并通过代码示例来帮助大......
  • 深入理解 React 的 Context API:从基础到高级应用
    深入理解React的ContextAPI:从基础到高级应用在React应用中,状态管理一直是一个重要且复杂的话题。虽然Redux和MobX等状态管理库提供了强大的解决方案,但有时候我们只需要一个简单的方式来在组件树中传递数据。React的ContextAPI就是为了解决这个问题而生的。今天,我们......
  • 解决 React 中 setInterval 无法更新状态的问题:长按加速的实现
    解决React中setInterval无法更新状态的问题:长按加速的实现在开发React应用时,我们经常会遇到需要定时更新组件状态的场景。setInterval是一个常用的定时器函数,但在React中使用它时,可能会遇到状态无法更新的问题。今天,我们就来深入探讨一下这个问题,并通过一个长按加速的例......
  • 深入探讨React表单组件:从基础到高级
    深入探讨React表单组件:从基础到高级大家好!今天我们来聊聊React中的表单组件。表单在前端开发中是非常常见的需求,无论是登录、注册还是数据提交,表单组件都扮演着重要的角色。本文将带你从基础到高级,深入了解React表单组件的使用和优化。基础知识在React中,表单元素(如<input>、<te......