2024-08-14
前端
00

目录

React的设计思想
1. 组件化(Component-Based Architecture)
什么是组件化?
优点:
2. 单向数据流(Unidirectional Data Flow)
什么是单向数据流?
优点:
3. 声明式编程(Declarative Programming)
什么是声明式编程?
优点:
4. 虚拟 DOM(Virtual DOM)
什么是虚拟 DOM?
优点:
5. 单一职责原则(Single Responsibility Principle)
什么是单一职责原则?
优点:
6. React 生命周期(Component Lifecycle)
什么是 React 生命周期?
优点:
JSX是什么
为什么React自定义组件首字母要大写?
原因解析
React组件为什么不能返回多个元素?
生命周期
1. 挂载阶段(Mounting)
React事件机制
React 事件机制的核心概念
常用组件 - Portal
常用组件 - Fragment
主要用途
使用方法
主要用途
使用方法
总结
React-Router
核心概念
总结
React Hooks
常用的 React Hooks

React的设计思想

React 的设计思想围绕着几个核心理念展开,这些理念指导了 React 的架构设计、开发模式以及生态系统的构建。以下是 React 的设计思想和核心理念:

1. 组件化(Component-Based Architecture)

什么是组件化?

React 的核心思想之一是组件化,即将用户界面分解成独立、可复用的组件,每个组件封装了自己的结构、样式和行为。组件之间可以嵌套、组合,构建复杂的用户界面。

优点:

  • 可复用性:组件可以在不同的页面或项目中复用,减少重复代码,提高开发效率。
  • 可维护性:组件封装了特定的功能或视图,界面逻辑清晰、职责单一,便于理解和维护。
  • 组合性:通过组合不同的组件,可以构建复杂的用户界面,同时保持代码的简洁和模块化。

2. 单向数据流(Unidirectional Data Flow)

什么是单向数据流?

在 React 中,数据通过组件树以单向的方式流动,父组件将数据通过 props 传递给子组件,子组件通过回调函数将事件或数据传回给父组件。这种单向数据流的模式使得数据流动更加可控、可预测。

优点:

  • 可预测性:单向数据流使得数据变化路径明确,便于调试和追踪。
  • 易于理解:数据流动的方向单一,减少了数据流动的复杂性,便于开发者理解和维护应用状态。
  • 更好地与状态管理结合:如 Redux、MobX 等状态管理工具可以更好地与单向数据流结合,管理全局状态。

3. 声明式编程(Declarative Programming)

什么是声明式编程?

React 提倡声明式编程,开发者只需描述组件应该“呈现什么”(UI的最终状态),而不需要描述“如何”去执行(操作 DOM 的步骤)。React 会根据状态的变化,自动高效地更新和渲染组件。

优点:

  • 简化 UI 逻辑:声明式编程使得 UI 逻辑更加清晰,开发者可以专注于描述界面应该呈现的样子,而不需要手动管理 DOM 操作。
  • 减少副作用:由于 React 自动处理 UI 更新,开发者不需要担心直接操作 DOM 可能导致的副作用问题。

4. 虚拟 DOM(Virtual DOM)

什么是虚拟 DOM?

React 使用虚拟 DOM 技术,通过在内存中创建一个轻量级的 DOM 树副本,当组件状态变化时,React 会首先在虚拟 DOM 中进行比较(diffing),找到最小的变化集(reconciliation),然后再将这些变化应用到真实 DOM 中。

优点:

  • 提高性能:虚拟 DOM 的 diffing 和 reconciliation 机制减少了直接操作真实 DOM 的次数,避免了频繁的 DOM 更新带来的性能开销。
  • 跨平台:虚拟 DOM 使得 React 可以在不同平台(如 Web、移动端)上使用相同的编程模型。

5. 单一职责原则(Single Responsibility Principle)

什么是单一职责原则?

React 强调组件的单一职责,即每个组件应只负责一件事情。通过将复杂的界面拆分成多个职责单一的小组件,React 提高了代码的可读性和可维护性。

优点:

  • 清晰的代码结构:每个组件只专注于完成一个功能或展示一个部分,代码结构更加清晰。
  • 易于测试:单一职责的组件更容易编写单元测试,从而提高代码质量。

6. React 生命周期(Component Lifecycle)

什么是 React 生命周期?

React 组件具有生命周期方法,这些方法在组件的创建、更新和销毁过程中自动触发。通过生命周期方法,开发者可以在特定的阶段执行代码,如在组件挂载时加载数据,或在组件更新时处理副作用。

优点:

  • 灵活性:生命周期方法为开发者提供了在组件各个阶段执行逻辑的机会,灵活应对不同的需求。
  • 高效管理资源:通过适当使用生命周期方法,可以优化资源管理,如在组件卸载时清理不必要的资源。

JSX是什么

JSX 是 React 中使用的一种语法扩展,使得在 JavaScript 中编写 HTML 标签成为可能,提供了一种更加简洁和直观的方式来构建用户界面。

JavaScript 是浏览器原生支持的脚本语言,JSX 最终会被编译为标准的 JavaScript,以供浏览器执行。

JSX 的引入简化了 React 组件的开发过程,使得代码更加可读、易于维护。

只要使用了jsx,就要引用react:

javascript
import React from "react"

为什么React自定义组件首字母要大写?

在 React 中,自定义组件的首字母需要大写,这是因为 React 使用大写字母来区分用户定义的组件和原生的 HTML 标签。这个约定在 React 内部的渲染机制中起到了重要的作用。

原因解析

  1. 区分原生 HTML 标签和自定义组件

    • 在 React 中,所有的原生 HTML 元素(如 <div><span> 等)都是小写的。而自定义组件通常是用 JavaScript 函数或类定义的,这些组件在 JSX 中使用时,React 会根据标签的首字母来判断它是一个原生 HTML 元素还是一个自定义组件。
    • 如果一个组件名以大写字母开头,React 会将其视为一个自定义组件,并尝试通过组件类或函数渲染它。
    • 如果以小写字母开头,React 会认为它是一个原生的 HTML 标签,或者是一个字符串常量,这样可能会导致组件无法正确渲染。

    示例

    jsx
    function MyComponent() { return <div>Hello, World!</div>; } const element = <MyComponent />; // React 将识别为自定义组件 const anotherElement = <mycomponent />; // React 会将其识别为一个未知的 HTML 标签,可能导致渲染错误
  2. JSX 语法的设计决定

    • JSX 是 JavaScript 的语法扩展,在 JSX 中,大写字母开头的元素会被编译为 React.createElement(ComponentName),而小写字母开头的元素则会被编译为 React.createElement('div') 这样的原生 HTML 标签。
    • 这意味着,如果自定义组件以小写字母开头,React 会尝试在 HTML 中寻找相应的标签,从而导致渲染问题。

    编译后的代码

    jsx
    <MyComponent />

    编译后类似于:

    javascript
    React.createElement(MyComponent);

    而:

    jsx
    <mycomponent />

    编译后类似于:

    javascript
    React.createElement('mycomponent');

    后者会导致 React 尝试渲染一个名为 mycomponent 的 HTML 标签,但这是不存在的,可能会导致渲染出一个空的 HTML 元素。

  3. 遵循 JavaScript 类和构造函数命名的惯例

    • 在 JavaScript 中,类名和构造函数名通常以大写字母开头。这是一个通用的编码惯例,React 也遵循了这一约定,以确保代码的一致性和可读性。
    • 大写字母开头的组件名让开发者能够快速识别哪些是自定义组件,哪些是普通的 HTML 标签,从而提高代码的可读性。

React组件为什么不能返回多个元素?

React 使用虚拟 DOM 来表示用户界面的结构。虚拟 DOM 是以树结构来表示的,每个组件在渲染时都会生成一个虚拟 DOM 树。

如果一个组件返回多个根元素,React 将无法确定它们的父子关系,从而无法正确构建虚拟 DOM 树。这会导致渲染逻辑的复杂化,增加 React 内部处理的难度。

生命周期

React 的组件生命周期指的是组件从创建、更新到销毁的整个过程。React 提供了一系列的生命周期方法(或钩子函数),允许开发者在组件的不同阶段执行特定的代码逻辑。这些生命周期方法可以分为三个主要阶段:挂载阶段更新阶段卸载阶段

1. 挂载阶段(Mounting)

挂载阶段是组件实例被创建并插入到 DOM 中的过程。在这个阶段,会依次调用以下生命周期方法:

  • constructor(props):

    • 这是组件的构造函数,在组件创建时最先被调用。通常在这里初始化组件的状态和绑定事件处理函数。
    • 注意:如果没有特殊需求,可以不定义 constructor,React 会默认调用它。
    jsx
    constructor(props) { super(props); this.state = { count: 0, }; }
  • static getDerivedStateFromProps(props, state):

    • 这是一个静态方法,在组件实例化或接收到新的 props 时调用,并在 render 方法之前调用。它用于根据 props 更新状态。
    • 注意:这是一个不常用的方法,仅在需要从 props 中派生出新的状态时使用。
    jsx
    static getDerivedStateFromProps(props, state) { if (props.someValue !== state.someValue) { return { someValue: props.someValue }; } return null; // 没有状态更新则返回 null }
  • render():

    • 必须实现的方法,负责返回要渲染的 JSX 或 React 元素。render 方法应该是纯函数,不应包含副作用。
    jsx
    render() { return <div>Hello, World!</div>; }
  • componentDidMount():

    • 在组件被挂载到 DOM 之后立即调用。在这个方法中可以进行诸如数据请求、DOM 操作等副作用。
    • 注意:这是一个常用的方法,用于初始化组件所需的外部数据或启动定时器等操作。
    jsx
    componentDidMount() { // 例如:数据请求 fetch('https://api.example.com/data') .then(response => response.json()) .then(data => this.setState({ data })); }

2. 更新阶段(Updating)

更新阶段发生在组件的 propsstate 发生变化时。此时,组件会重新渲染,并依次调用以下生命周期方法:

  • static getDerivedStateFromProps(props, state):

    • 和挂载阶段一样,该方法在组件接收到新的 props 或状态变化时调用,用于更新状态。
  • shouldComponentUpdate(nextProps, nextState):

    • 在接收到新的 propsstate 时调用,返回值为 truefalse,用来决定组件是否需要更新。可以通过该方法优化性能,避免不必要的渲染。
    jsx
    shouldComponentUpdate(nextProps, nextState) { // 只有当 props 或 state 发生实际变化时才更新 return nextProps.someValue !== this.props.someValue; }
  • render():

    • 和挂载阶段一样,render 方法用于渲染组件的 UI。每次更新时都会调用此方法。
  • getSnapshotBeforeUpdate(prevProps, prevState):

    • 在更新前获取 DOM 的一些信息或状态(如滚动位置),返回值会作为参数传递给 componentDidUpdate 方法。
    jsx
    getSnapshotBeforeUpdate(prevProps, prevState) { if (prevProps.list.length < this.props.list.length) { return this.listRef.scrollHeight; // 获取更新前的滚动高度 } return null; }
  • componentDidUpdate(prevProps, prevState, snapshot):

    • 在组件更新后立即调用。通常用于处理更新后的 DOM 操作或数据请求。snapshot 参数是 getSnapshotBeforeUpdate 方法的返回值。
    jsx
    componentDidUpdate(prevProps, prevState, snapshot) { if (snapshot !== null) { this.listRef.scrollTop += snapshot; // 根据之前的快照值调整滚动位置 } }

3. 卸载阶段(Unmounting)

卸载阶段是在组件即将从 DOM 中移除时调用的,这个阶段只有一个生命周期方法:

  • componentWillUnmount():

    • 在组件从 DOM 中移除之前立即调用。用于执行清理操作,如取消定时器、取消网络请求或清除在 componentDidMount 中创建的资源。
    jsx
    componentWillUnmount() { clearInterval(this.interval); }

4. 错误处理阶段(Error Handling)

React 16 引入了新的生命周期方法,用于处理组件中的错误:

  • static getDerivedStateFromError(error):

    • 在渲染期间、生命周期方法或子组件的构造函数中抛出错误时调用。允许组件更新其状态以展示错误界面。
    jsx
    static getDerivedStateFromError(error) { return { hasError: true }; // 更新状态,显示错误界面 }
  • componentDidCatch(error, info):

    • 在组件的子组件抛出错误时调用。可以用于记录错误信息。
    jsx
    componentDidCatch(error, info) { // 可以将错误信息发送到日志服务 logErrorToService(error, info); }

总结

React 的生命周期方法为开发者提供了在组件的不同阶段执行特定操作的机会。理解和合理使用这些生命周期方法,可以帮助开发者更好地管理组件的状态、优化性能,并在组件的整个生命周期内有效地处理各种任务。

  • 挂载阶段constructorgetDerivedStateFromPropsrendercomponentDidMount
  • 更新阶段getDerivedStateFromPropsshouldComponentUpdaterendergetSnapshotBeforeUpdatecomponentDidUpdate
  • 卸载阶段componentWillUnmount
  • 错误处理getDerivedStateFromErrorcomponentDidCatch

React事件机制

React 的事件机制与传统的 HTML DOM 事件处理有一些不同,它引入了一种名为 合成事件(Synthetic Event) 的机制。这种机制在跨浏览器兼容性、性能优化以及事件处理的一致性方面提供了许多好处。

React 事件机制的核心概念

  1. 合成事件(Synthetic Event)

    • React 使用合成事件来封装原生的浏览器事件。合成事件是跨浏览器的事件包装层,提供了与原生事件相同的接口,但其行为在所有浏览器中是一致的。
    • 通过合成事件,React 解决了不同浏览器之间事件实现的差异,使得开发者可以在编写事件处理代码时无需考虑浏览器兼容性问题。
  2. 事件委托(Event Delegation)

    • React 并不将事件处理程序直接绑定到实际的 DOM 元素上,而是使用事件委托的方式。在组件树的根节点上绑定一个统一的事件处理程序,当事件发生时,React 会判断事件发生的目标元素,并调用相应的事件处理程序。
    • 这种机制大大减少了需要绑定的事件处理程序的数量,从而优化了性能,尤其是在需要处理大量元素的情况下。
  3. 自动事件绑定

    • 在 JSX 中,事件处理程序通过元素的属性进行绑定,例如 onClickonChange 等。React 会自动将这些事件处理程序绑定到合适的元素上。
    • 这些事件处理程序的命名遵循驼峰命名法,例如 onClickonMouseEnter 等,而不是传统 HTML 中的 onclickonmouseover 等。

    示例

    jsx
    function MyButton() { function handleClick() { console.log('Button clicked'); } return ( <button onClick={handleClick}> Click me </button> ); }
  4. 事件传播与阻止

    • 合成事件同样支持事件的捕获与冒泡机制,类似于原生的 DOM 事件处理。开发者可以使用 stopPropagation() 方法来阻止事件传播。
    • 事件处理函数的第一个参数就是合成事件对象,类似于原生事件对象,但它是在 React 环境中被封装和增强的。

    示例

    jsx
    function handleClick(event) { event.stopPropagation(); // 阻止事件冒泡 console.log('Button clicked'); }
  5. 事件的回收与优化

    • React 出于性能考虑,会将合成事件对象进行回收和重用。因此,合成事件的某些属性在事件处理函数的异步调用中可能不可用。如果需要在异步操作中访问事件属性,可以在事件处理函数中调用 event.persist() 方法来保留事件对象。

    示例

    jsx
    function handleClick(event) { event.persist(); // 防止事件对象被回收 setTimeout(() => { console.log(event.type); // 此时依然可以访问事件对象的属性 }, 1000); }

React 事件与原生事件的区别

  1. 命名方式

    • React 事件处理程序采用驼峰命名法,例如 onClickonChange,而原生 HTML 事件处理程序使用全小写的命名方式,如 onclickonchange
  2. 事件绑定的方式

    • 在 React 中,事件处理程序在元素渲染时被绑定,而不是在 DOM 元素实际挂载时。这意味着当 JSX 被渲染时,React 已经为该元素处理好了所有事件绑定。
  3. 事件处理中的 this

    • 在类组件中,事件处理程序中的 this 默认不会绑定到组件实例上,需要手动绑定或使用箭头函数。
    • 在函数组件中,事件处理程序可以直接使用组件内的状态和上下文。

    示例(类组件)

    jsx
    class MyButton extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick() { console.log('Button clicked', this); } render() { return ( <button onClick={this.handleClick}> Click me </button> ); } }

    示例(函数组件)

    jsx
    function MyButton() { const handleClick = () => { console.log('Button clicked'); }; return ( <button onClick={handleClick}> Click me </button> ); }
  4. 跨浏览器一致性

    • React 的合成事件处理在所有浏览器中都表现一致,开发者不必担心浏览器的兼容性问题。而在原生 DOM 事件处理中,不同浏览器可能会有不同的行为或事件模型。

常用组件 - Portal

让子组件渲染在除了父组件之外的dom节点的方式。通常情况下,React 组件会渲染在它们在组件树中的位置对应的 DOM 结构中,但是 Portal 提供了一种将子元素渲染到不同 DOM 子树中的能力,而不改变组件的层级结构。

javascript
ReactDom.createPortal(child, container)

常用于弹框、提示框。

常用组件 - Fragment

Fragment 是 React 提供的一种包裹组件的方式,用于将多个元素组合在一起,而不会在 DOM 中增加额外的节点。通常情况下,React 组件需要返回一个单一的根元素,而 Fragment 允许组件返回多个元素,而不需要额外的包裹 div 或其他元素。

主要用途

  1. 减少不必要的 DOM 元素:在不影响样式和结构的情况下,使用 Fragment 可以避免在 DOM 中生成额外的节点,例如不需要的 div 包裹层。
  2. 优化性能:通过减少不必要的嵌套元素,Fragment 可以帮助保持更简洁的 DOM 结构,有助于提高页面渲染性能。

使用方法

有两种方式使用 Fragment

  1. 标准的 Fragment 语法

    jsx
    import React, { Fragment } from 'react'; function MyComponent() { return ( <Fragment> <h1>Title</h1> <p>This is a paragraph.</p> </Fragment> ); }
  2. 简写语法(空标签):

    jsx
    function MyComponent() { return ( <> <h1>Title</h1> <p>This is a paragraph.</p> </> ); }

常用组件 - Context

Context 是 React 提供的一种解决组件间共享数据(比如全局状态)的机制,而不需要通过逐层传递 propsContext 可以帮助你在组件树的深层嵌套中传递数据,而不必手动通过每一级组件的 props 传递。

主要用途

  1. 全局状态管理Context 通常用于在整个应用中共享一些全局数据,比如当前用户信息、主题设置、语言环境等。
  2. 避免“props 钻取”:当一个组件需要从其上层组件获取数据,而这个数据并非直接与其父组件相关时,Context 可以避免一层层地通过 props 传递数据。

使用方法

  1. 创建 Context

    • 使用 React.createContext() 创建一个 Context 对象。
    jsx
    const MyContext = React.createContext(defaultValue);
  2. 提供数据(Provider)

    • 使用 Context.Provider 包裹组件树,并通过 value 属性传递数据。所有包裹在 Provider 内部的组件都可以访问这个数据。
    jsx
    <MyContext.Provider value={/* some value */}> <MyComponent /> </MyContext.Provider>
  3. 消费数据(Consumer)

    • 使用 Context.Consumer 或者 useContext 钩子来获取 Context 中的数据。

    使用 Consumer

    jsx
    <MyContext.Consumer> {value => /* render something based on the context value */} </MyContext.Consumer>

    使用 useContext 钩子

    jsx
    const value = React.useContext(MyContext);

简单示例

jsx
// 1. 创建 Context const ThemeContext = React.createContext('light'); function App() { // 2. 使用 Provider 提供数据 return ( <ThemeContext.Provider value="dark"> <Toolbar /> </ThemeContext.Provider> ); } function Toolbar() { return ( <div> <ThemedButton /> </div> ); } function ThemedButton() { // 3. 使用 useContext 消费数据 const theme = React.useContext(ThemeContext); return <button className={theme}>I am styled by theme context!</button>; }

总结

  • Context 用于在 React 应用中全局共享数据,避免“props 钻取”。
  • 通过 Provider 提供数据,使用 ConsumeruseContext 钩子来消费数据。
  • 适合用于全局状态、主题、语言等不经常变化且需要在多个组件之间共享的数据。

React-Router

React Router 是 React 的标准路由库,用于在单页应用(SPA)中实现客户端路由。它允许开发者在 React 应用中定义和管理不同的页面或视图,并根据 URL 的变化来渲染相应的组件,而无需重新加载整个页面。

核心概念

  1. Router(路由器)

    • BrowserRouterHashRouter 是两种常用的路由器组件。
    • BrowserRouter 使用 HTML5 的 history API 实现路由,URL 形式为标准的路径结构。
    • HashRouter 使用 URL 的哈希部分(#)来管理路由,URL 形式为 http://example.com/#/path
  2. Route(路由)

    • Route 组件用于定义 URL 路径与 React 组件之间的映射关系。当 URL 与某个 Routepath 属性匹配时,React Router 会渲染该路径对应的组件。
    jsx
    <Route path="/home" component={HomeComponent} />
  3. Link(链接)

    • Link 组件用于创建可点击的导航链接,类似于 HTML 的 <a> 标签,但它不会触发页面刷新,而是使用 React Router 的路由机制来进行导航。
    jsx
    <Link to="/home">Go to Home</Link>
  4. Switch(切换)

    • Switch 组件用于确保只渲染一个匹配的 Route。当多个 Routepath 属性与当前 URL 匹配时,Switch 只会渲染第一个匹配的 Route
    jsx
    <Switch> <Route path="/about" component={AboutComponent} /> <Route path="/home" component={HomeComponent} /> </Switch>
  5. Redirect(重定向)

    • Redirect 组件用于将用户从一个路径重定向到另一个路径。
    jsx
    <Redirect from="/old-path" to="/new-path" />
  6. useParams、useLocation、useHistory

    • 这些是 React Router 提供的钩子,用于在函数组件中访问路由参数、当前路径和浏览历史。
    jsx
    const { id } = useParams(); // 获取URL中的参数 const location = useLocation(); // 获取当前路径信息 const history = useHistory(); // 访问浏览历史,用于导航

简单示例

jsx
import React from 'react'; import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom'; function Home() { return <h2>Home Page</h2>; } function About() { return <h2>About Page</h2>; } function App() { return ( <Router> <nav> <Link to="/home">Home</Link> <Link to="/about">About</Link> </nav> <Switch> <Route path="/home" component={Home} /> <Route path="/about" component={About} /> <Route path="/" exact> <h2>Welcome to the App</h2> </Route> </Switch> </Router> ); } export default App;

在这个示例中:

  • Router 包裹了整个应用,管理着应用的路由行为。
  • Link 创建了导航链接,用于在不同页面之间切换。
  • Route 定义了路径与组件的映射关系。
  • Switch 确保在一个时刻只渲染一个路径匹配的组件。

总结

  • React Router 是用于 React 应用的路由解决方案,帮助管理单页应用中的页面导航。
  • 它通过 RouteLinkSwitch 等组件来实现路由管理和页面切换。
  • 支持 URL 参数、重定向、动态路由、嵌套路由等高级功能,适合构建复杂的单页应用。

React Hooks

React Hooks 是 React 16.8 引入的一组新特性,它允许你在函数组件中使用状态和其他 React 特性,而不需要编写类组件。Hooks 提升了函数组件的功能,使其能够处理状态、生命周期、上下文等高级功能,从而简化了组件的编写和复用。

常用的 React Hooks

  1. useState

    • 用来管理组件中的状态
    • 返回一个状态变量和一个更新该状态的函数。

    示例

    jsx
    import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // 初始化状态为 0 return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
  2. useEffect

    • 用来处理副作用(如数据获取、订阅、手动修改 DOM 等)。
    • useEffect 可以看作是 componentDidMountcomponentDidUpdatecomponentWillUnmount 的组合。

    示例

    jsx
    import React, { useEffect } from 'react'; function Example() { useEffect(() => { document.title = "Component Mounted"; return () => { document.title = "Component Unmounted"; // 清理操作 }; }, []); // 空数组表示仅在组件挂载和卸载时执行 return <div>Check the document title!</div>; }
  3. useContext

    • 用来使用上下文,简化了通过 props 逐层传递数据的过程。
    • 通过 useContext,组件可以直接访问上下文数据。

    示例

    jsx
    import React, { useContext } from 'react'; const ThemeContext = React.createContext('light'); function ThemedButton() { const theme = useContext(ThemeContext); return <button className={theme}>Button with {theme} theme</button>; }
  4. useReducer

    • 用来管理更复杂的状态逻辑,是 useState 的替代方案。
    • useReducer 接受一个 reducer 函数和一个初始状态,返回当前状态和一个 dispatch 函数。

    示例

    jsx
    import React, { useReducer } from 'react'; function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: return state; } } function Counter() { const [state, dispatch] = useReducer(reducer, { count: 0 }); return ( <div> <p>Count: {state.count}</p> <button onClick={() => dispatch({ type: 'increment' })}>Increment</button> <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button> </div> ); }
  5. useRef

    • 用来访问 DOM 元素或保存任意值,在组件的整个生命周期内保持不变。
    • 通常用于存储对 DOM 元素的引用或保存不会触发重新渲染的变量。

    示例

    jsx
    import React, { useRef } from 'react'; function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => { inputEl.current.focus(); // 使用 useRef 访问 DOM 元素 }; return ( <div> <input ref={inputEl} type="text" /> <button onClick={onButtonClick}>Focus the input</button> </div> ); }

本文作者:Jeff Wu

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!