react速通-3

三十四、redux开发者工具

7.求和案例_redux开发者工具的使用

(1). yarn add redux-devtools-extension

(2). store中进行配置

jsx 复制代码
 import { composeWithDevTools } from 'redux-devtools-extension'
const store = createStore(allReducer, composeWithDevTools(applyMiddleware(thunk)))

三十五、setState讲解

React setState 核心知识点


一、setState 的两种用法

1. 对象式 setState

  • 语法setState(stateChangeObj, [callback])

  • 说明:

    • stateChangeObj:直接传入一个对象,描述要修改的状态。
    • callback(可选):状态更新完成、render() 执行后才会调用的回调函数,可在其中获取最新状态。

2. 函数式 setState

  • 语法setState(updaterFunc, [callback])

  • 说明:

    • updaterFunc:一个函数,接收上一次的 stateprops 作为参数,返回一个状态更新对象。
    • callback(可选):和对象式用法中的回调作用一致。

二、两种写法的关系

对象式 setState 是函数式 setState 的语法糖,本质上 React 内部最终都会将对象式写法转换为函数式写法执行。


三、使用原则(核心考点)

  1. 新状态不依赖原状态 :优先使用对象式 setState,写法更简洁。
  2. 新状态依赖原状态 :必须使用函数式 setState ,避免因 setState 异步合并导致的状态更新错误。
  3. 获取最新状态 :如果需要在 setState 执行后立刻拿到更新后的状态值,只能在第二个参数 callback 回调函数中读取,不能直接在 setState 之后同步读取 this.state

三十六、React 路由懒加载(lazyLoad)知识点


一、核心概念

路由懒加载,就是只有当用户访问到对应路由时,才加载该路由组件的代码,而不是在应用启动时一次性加载所有组件。

  • 作用:减少首屏加载时间,优化应用性能,避免打包后的主文件过大。
  • 核心 API:React.lazy() + import() + <Suspense>

二、实现步骤

1. 使用 React.lazy() 动态导入路由组件

通过 lazy() 配合 import() 函数,实现组件的代码分割,让路由组件被单独打包成不同的文件。

jsx 复制代码
import { lazy } from 'react';

// 动态导入组件,只有访问该路由时才加载代码
const Login = lazy(() => import('@/pages/Login'));
const Home = lazy(() => import('@/pages/Home'));

2. 使用 <Suspense> 包裹路由,指定加载时的 fallback

<Suspense> 组件可以在路由组件加载完成前,显示一个自定义的 loading 界面,避免页面空白。

jsx 复制代码
import { Suspense } from 'react';
import { Switch, Route, Redirect } from 'react-router-dom';

// fallback 就是加载过程中显示的内容
<Suspense fallback={<h1>loading......</h1>}>
  <Switch>
    <Route path="/login" component={Login} />
    <Route path="/home" component={Home} />
    <Redirect to="/login" />
  </Switch>
</Suspense>

三十七、React Hooks 核心知识点


一、React Hook 基础概念

  1. 定义:Hook 是 React 16.8.0 版本新增的特性 / 新语法。
  2. 作用 :可以让你在函数组件 中使用 state 以及其他的 React 特性,不再依赖类组件。

二、三个常用的 Hook

  1. State HookReact.useState()
  2. Effect HookReact.useEffect()
  3. Ref HookReact.useRef()

三、State Hook(useState

  1. 作用 :让函数组件也可以有 state 状态,并进行状态数据的读写操作。

  2. 语法

    jsx 复制代码
    const [xxx, setXxx] = React.useState(initValue)
  3. 参数与返回值说明

    • 参数:第一次初始化时指定的值,会在内部缓存起来。
    • 返回值:包含 2 个元素的数组,第 1 个为当前状态值,第 2 个为更新状态值的函数。
  4. 更新状态的两种写法

    • 写法一:setXxx(newValue)

      直接传入非函数值,会用新值覆盖原状态。

    • 写法二:setXxx(value => newValue)

      传入一个函数,接收原本的状态值,返回新的状态值,内部会用新值覆盖原状态。

示例代码

jsx 复制代码
function Demo(){
  console.log('Demo');

  // 定义状态count和更新函数setCount,初始值为0
  const [count, setCount] = React.useState(0)
  // 定义状态name和更新函数setName,初始值为'tom'
  const [name, setName] = React.useState('tom')

  // 增加count的回调
  function add(){
    // 依赖原状态更新时,推荐使用函数式写法
    setCount(count => count + 1)
  }

  // 修改name的回调
  function changeName(){
    // 不依赖原状态,直接传入新值即可
    setName('jack')
  }

  return (
    <div>
      <h2>当前求和为:{count}</h2>
      <h2>我的名字是:{name}</h2>
      <button onClick={add}>点我+1</button>
      <button onClick={changeName}>点我改名</button>
    </div>
  )
}

export default Demo

四、Effect Hook(useEffect

  1. 作用:可以让你在函数组件中执行副作用操作,常用于模拟类组件中的生命周期钩子。

  2. 常见的副作用操作

    • ajax 请求获取数据
    • 设置订阅 / 启动定时器
    • 手动更改真实 DOM
  3. 基础语法

    js 复制代码
    useEffect(() => {
      // 1. 副作用执行区:在此可以执行任何带副作用操作
    
      return () => {
        // 2. 清理函数:在组件卸载前/副作用重新执行前执行
        // 用于收尾工作,比如清除定时器、取消订阅等
      }
    }, [stateValue]) // 3. 依赖数组

依赖数组的不同用法

依赖数组形式 执行时机 对应类组件生命周期
不写依赖数组 每次组件渲染后都执行 componentDidMount + componentDidUpdate
空数组 [] 仅在组件第一次渲染后执行一次 componentDidMount
包含状态值 [stateValue] 首次渲染后执行,且当 stateValue 变化时再次执行 componentDidMount + componentDidUpdate(仅监听指定状态)

4、与类组件生命周期的对应关系

useEffect 可以看作以下三个生命周期钩子的组合:

  1. componentDidMount:组件挂载后执行(通过空依赖数组实现)
  2. componentDidUpdate:组件更新后执行(通过依赖数组监听状态变化实现)
  3. componentWillUnmount:组件卸载前执行(通过返回的清理函数实现)

五、React Ref Hook


一、基础定义

useRef 是 React 提供的 Ref Hook,用于在函数组件中创建一个可变的 ref 对象,可以用来存储 / 查找组件内的 DOM 标签或任意其他数据。


二、语法

jsx 复制代码
const refContainer = useRef(initialValue);
  • useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的 initialValue
  • 该对象在组件的整个生命周期内保持不变,每次渲染都会返回同一个对象引用。

三、核心作用

  1. 保存 / 获取 DOM 元素

    功能上与类组件的 React.createRef() 完全一致,可以直接绑定到元素上,用于获取其 DOM 实例。

    jsx 复制代码
    function Demo() {
      const inputRef = useRef(null);
    
      function handleClick() {
        // 通过 ref.current 获取 DOM 元素
        inputRef.current.focus();
      }
    
      return (
        <div>
          <input ref={inputRef} type="text" />
          <button onClick={handleClick}>聚焦输入框</button>
        </div>
      );
    }
  2. 存储任意可变数据

    useRef 不仅可以存 DOM,还可以用来保存组件中不参与渲染的可变数据,比如定时器 ID、上一次的状态值等。

    jsx 复制代码
    function Demo() {
      const timerRef = useRef(null);
    
      useEffect(() => {
        timerRef.current = setInterval(() => {
          console.log("定时器运行中");
        }, 1000);
    
        return () => {
          // 组件卸载时清除定时器
          clearInterval(timerRef.current);
        };
      }, []);
    }

四、关键特性

  • 组件重新渲染时,useRef 返回的对象不会改变。
  • 修改 .current 属性的值不会触发组件重新渲染 ,这是它和 useState 的核心区别。
  • 可以用来保存上一次的状态值,解决闭包陷阱问题。

三十八、React Fragment 核心知识点

Fragment 是 React 提供的一个内置组件,专门用来解决组件必须返回单个根节点的限制,又不会额外生成 DOM 节点。


一、为什么需要 Fragment

在 React 中,组件的 render 函数(或函数组件的返回值)必须只能返回单个根节点

如果我们直接写多个并列元素,会报错:

jsx 复制代码
// ❌ 错误写法:返回了多个根节点
function App() {
  return (
    <h1>标题</h1>
    <p>段落</p>
  );
}

以前我们常用 <div> 包裹,但这会在 DOM 中多生成一层不必要的 <div>,可能导致样式问题或 DOM 结构冗余。Fragment 就是为了解决这个问题而生的。


二、两种基本用法

1. 完整写法(推荐在复杂场景使用)

jsx 复制代码
import { Fragment } from 'react';

function App() {
  return (
    <Fragment>
      <h1>标题</h1>
      <p>段落</p>
    </Fragment>
  );
}

渲染结果:不会生成额外的 DOM 节点,直接输出:

复制代码
<h1>标题</h1>
<p>段落</p>

2. 短语法(最常用,面试常考)

React 提供了更简洁的空标签 <> 作为 Fragment 的简写形式:

jsx 复制代码
function App() {
  return (
    <>
      <h1>标题</h1>
      <p>段落</p>
    </>
  );
}

效果和完整写法完全一致,也是开发中最常用的方式。


三、Fragment 的核心特性

  1. 不渲染额外 DOM:它只是一个逻辑容器,不会在页面上生成任何真实的 HTML 标签,避免了无意义的节点嵌套。

  2. 支持 key 属性

    • 完整写法 <Fragment> 可以接收 key 属性,用于列表渲染场景:

      jsx 复制代码
      function List({ items }) {
        return (
          <dl>
            {items.map(item => (
              <Fragment key={item.id}>
                <dt>{item.term}</dt>
                <dd>{item.description}</dd>
              </Fragment>
            ))}
          </dl>
        );
      }
    • 注意:短语法 <> 不支持 key 或其他属性 ,需要传 key 时必须用完整写法。

  3. 可以接收子节点 :和普通组件一样,Fragment 可以包含多个子元素,实现多根节点返回。


四、常见使用场景

  1. 组件需要返回多个并列元素(如列表项、表格的单元格)
  2. 不想在 DOM 中引入额外的包裹节点(避免影响 CSS 样式或选择器)
  3. 列表渲染中,需要为多个元素添加同一个 key 属性 (如 <dl> 中的 <dt><dd> 配对)

五、面试高频考点

  1. Fragmentdiv 的区别

    • div 会渲染真实的 DOM 节点,而 Fragment 不会,仅作为逻辑容器。
    • Fragment 不会影响页面结构和样式,而多余的 div 可能导致布局问题。
  2. 短语法 <> 和完整写法 <Fragment> 的区别

    • 短语法更简洁,但不支持 key 和其他属性。
    • 完整写法支持 key,适用于列表渲染场景。

三十九、context

一、什么时候用 Context?

  • 多个层级的组件需要共享数据
  • 比如:主题、语言、用户信息、全局配置
  • 不想用 Redux 又想跨层传值时

一句话:爷孙、多层组件通信,用 Context 最方便


二、三个核心 API

1. React.createContext()

创建一个上下文对象。

js 复制代码
const MyContext = React.createContext(defaultValue)

2. <MyContext.Provider>

数据提供者,用来提供数据

jsx 复制代码
<MyContext.Provider value={共享的数据}>
  {/* 所有子组件都能拿到 value */}
</MyContext.Provider>

3. <MyContext.Consumer> / useContext

数据消费者,用来读取数据

  • 类组件用 Consumer
  • 函数组件用 useContext 钩子

三、函数组件用法(最常用)

1. 创建 Context

jsx 复制代码
// ThemeContext.js
import { createContext } from 'react'
const ThemeContext = createContext()
export default ThemeContext

2. 顶层提供数据

jsx 复制代码
import ThemeContext from './ThemeContext'

function App() {
  return (
    <ThemeContext.Provider value={{ color: 'red' }}>
      <Child />
    </ThemeContext.Provider>
  )
}

3. 后代组件使用数据

jsx 复制代码
import { useContext } from 'react'
import ThemeContext from './ThemeContext'

function Child() {
  const theme = useContext(ThemeContext)
  return <div style={{ color: theme.color }}>文字</div>
}

四、类组件用法

jsx 复制代码
class Child extends React.Component {
  static contextType = ThemeContext
  render() {
    return <div>{this.context.color}</div>
  }
}

或者用 Consumer:

jsx 复制代码
<ThemeContext.Consumer>
  {value => <div>{value.color}</div>}
</ThemeContext.Consumer>

四十、pureComponent

四十一、render props


四十二、ErrorBoundary

相关推荐
心连欣2 小时前
从静态页面到动态交互:DOM操作的核心API解析
前端·javascript·api
零瓶水Herwt2 小时前
Javascript常用设计模式
javascript
风骏时光牛马2 小时前
C Shell脚本编程与系统管理技术实践指南
javascript
烛衔溟2 小时前
TypeScript this 参数类型与全局 this
javascript·ubuntu·typescript
qq_12084093712 小时前
Three.js 工程向:GLTFLoader 管线、Draco/KTX2 与资源管理
开发语言·javascript·ecmascript
光影少年2 小时前
Monorepo架构是什么,如何学习Monorepo架构?
前端·学习·架构·前端框架
billy_huang2 小时前
Capacitor的基本使用
javascript·android studio
研☆香3 小时前
聊一聊js中的正则表达式的应用
前端·javascript·正则表达式
qq_12084093713 小时前
Three.js 工程向:Clock、deltaTime 与固定步长主循环
开发语言·javascript·ecmascript