标签: React

  • 学习如何驯服React的useCallback钩子

    学习如何驯服React的useCallback钩子

    React.js近年来广受欢迎,这已经不是什么秘密了。它现在是许多互联网上最杰出的参与者(包括Facebook和WhatsApp)的首选JavaScript库。

    它兴起的主要原因之一是在16.8版本中引入了钩子。React钩子允许您在不编写类组件的情况下利用React函数。现在,带有钩子的功能组件已成为开发人员使用React的首选结构。

    在这篇博文中,我们将深入研究一个特定的钩子useCallback——因为它涉及函数式编程的一个基本部分,即记忆化。您将确切地知道如何以及何时使用useCallback钩子并充分利用其性能增强功能。

    1. 什么是Memoization?
    2. 渲染和反应
    3. React useCallback的性能优势
    4. React useCallback的缺点
    5. React使用回调示例

    什么是Memoization?

    Memoization是当一个复杂的函数存储它的输出以便下次使用相同的输入调用它时。它类似于缓存,但在本地级别上。它可以跳过任何复杂的计算并更快地返回输出,因为它已经计算过了。

    这会对内存分配和性能产生重大影响,而这种压力正是useCallback钩子的目的所在。

    React的useCallback与useMemo

    在这一点上,值得一提的是,useCallback与另一个名为useMemo的钩子很好地配对。我们将讨论它们,但在这篇文章中,我们将把重点放在useCallback主要话题上。

    关键区别在于useMemo返回一个记忆值,而useCallback返回一个记忆函数。这意味着useMemo用于存储计算值,同时useCallback返回一个您可以稍后调用的函数。

    这些钩子会给你一个缓存的版本,除非它们的依赖项之一(例如状态或道具)发生变化。

    让我们看一下这两个函数的作用:

    import { useMemo, useCallback } from ‘react’
    const values = [3, 9, 6, 4, 2, 1]
    // This will always return the same value, a sorted array. Once the values array changes then this will recompute.
    const memoizedValue = useMemo(() => values.sort(), [values])
    // This will give me back a function that can be called later on. It will always return the same result unless the values array is modified.
    const memoizedFunction = useCallback(() => values.sort(), [values])
    import { useMemo, useCallback } from ‘react’
    const values = [3, 9, 6, 4, 2, 1]
    // This will always return the same value, a sorted array. Once the values array changes then this will recompute.
    const memoizedValue = useMemo(() => values.sort(), [values])
    // This will give me back a function that can be called later on. It will always return the same result unless the values array is modified.
    const memoizedFunction = useCallback(() => values.sort(), [values])
    import { useMemo, useCallback } from 'react'
    const values = [3, 9, 6, 4, 2, 1]
    // This will always return the same value, a sorted array. Once the values array changes then this will recompute.
    const memoizedValue = useMemo(() => values.sort(), [values])
    // This will give me back a function that can be called later on. It will always return the same result unless the values array is modified.
    const memoizedFunction = useCallback(() => values.sort(), [values])

    上面的代码片段是一个人为的示例,但显示了两个回调之间的区别:

    1. memoizedValue会变成数组[1, 2, 3, 4, 6, 9]。只要values变量保持不变,memoizedValue它就会保持不变,并且永远不会重新计算。
    2. memoizedFunction将是一个返回数组的函数[1, 2, 3, 4, 6, 9]

    这两个回调的好处是它们会被缓存并一直存在,直到依赖数组发生变化。这意味着在渲染时,它们不会被垃圾收集。

    渲染和React

    为什么在React中记忆很重要?

    它与React如何渲染你的组件有关。React使用存储在内存中的虚拟DOM来比较数据并决定更新什么。

    虚拟DOM帮助React提高性能并让您的应用程序保持快速。默认情况下,如果您的组件中的任何值发生更改,整个组件将重新渲染。这使得React对用户输入具有“反应性”,并允许屏幕更新而无需重新加载页面。

    您不想渲染组件,因为更改不会影响该组件。这就是通过useCallbackuseMemo进行记忆的地方。

    当React重新渲染你的组件时,它也会重新创建你在组件中声明的函数。

    请注意,当比较一个函数与另一个函数的相等性时,它们总是为假的。因为函数也是一个对象,所以它只会等于它自己:

    // these variables contain the exact same function but they are not equal
    const hello = () => console.log(‘Hello Matt’)
    const hello2 = () => console.log(‘Hello Matt’)
    hello === hello2 // false
    hello === hello // true
    // these variables contain the exact same function but they are not equal
    const hello = () => console.log(‘Hello Matt’)
    const hello2 = () => console.log(‘Hello Matt’)
    hello === hello2 // false
    hello === hello // true
    // these variables contain the exact same function but they are not equal
    const hello = () => console.log('Hello Matt')
    const hello2 = () => console.log('Hello Matt')
    hello === hello2 // false
    hello === hello // true

    换句话说,当React重新渲染你的组件时,它会将在你的组件中声明的任何函数都视为新函数。

    这在大多数情况下都很好,简单的函数很容易计算并且不会影响性能。但是其他时候,当您不希望该功能被视为新功能时,您可以依靠useCallback来帮助您。

    你可能会想,“我什么时候不希望一个函数被视为一个新函数?” 好吧,在某些情况下useCallback更有意义:

    1. 您将函数传递给另一个也被记忆的组件(useMemo
    2. 你的函数有一个需要记住的内部状态
    3. 您的函数是另一个钩子的依赖项,例如useEffect

    React useCallback的性能优势

    如果useCallback使用得当,它可以帮助加速您的应用程序并防止组件在不需要时重新渲染。

    例如,假设您有一个组件,它获取大量数据并负责以图表或图形的形式显示该数据,如下所示:

     

    使用React组件生成的条形图

    使用React组件生成的条形图

     

    假设您的数据可视化组件的父组件重新渲染,但更改的道具或状态不会影响该组件。在这种情况下,您可能不想或不需要重新渲染它并重新获取所有数据。避免这种重新渲染和重新获取可以节省用户的带宽并提供更流畅的用户体验。

    React useCallback的缺点

    虽然这个钩子可以帮助你提高性能,但它也有它的缺陷。在使用useCallback(和useMemo)之前,需要考虑以下几点:

    • 垃圾收集: React将丢弃其他尚未记忆的函数以释放内存。
    • 内存分配:与垃圾回收类似,你拥有的记忆功能越多,需要的内存就越多。另外,每次你使用这些回调时,React中都有一堆代码需要使用更多的内存来为你提供缓存的输出。
    • 代码复杂性:当您开始在这些钩子中包装函数时,您会立即增加代码的复杂性。现在需要更多地了解为什么使用这些钩子并确认它们被正确使用。

    意识到以上这些陷阱可以让你省去自己跌跌撞撞的头痛。在考虑使用useCallback时,请确保性能优势大于缺点。

    React使用回调示例

    下面是一个带有Button组件和Counter组件的简单设置。Counter有两个状态并渲染出两个Button组件,每个组件将更新Counter组件状态的一个单独部分。

    Button组件有两个props:handleClick和name。每次呈现Button时,它都会登录到控制台。

    import { useCallback, useState } from ‘react’
    const Button = ({handleClick, name}) => {
    console.log(`${name} rendered`)
    return <button onClick={handleClick}>{name}</button>
    }
    const Counter = () => {
    console.log(‘counter rendered’)
    const [countOne, setCountOne] = useState(0)
    const [countTwo, setCountTwo] = useState(0)
    return (
    <>
    {countOne} {countTwo}
    <Button handleClick={() => setCountOne(countOne + 1)} name=“button1” />
    <Button handleClick={() => setCountTwo(countTwo + 1)} name=“button1” />
    </>
    )
    }
    import { useCallback, useState } from ‘react’
    const Button = ({handleClick, name}) => {
    console.log(`${name} rendered`)
    return <button onClick={handleClick}>{name}</button>
    }
    const Counter = () => {
    console.log(‘counter rendered’)
    const [countOne, setCountOne] = useState(0)
    const [countTwo, setCountTwo] = useState(0)
    return (
    <>
    {countOne} {countTwo}
    <Button handleClick={() => setCountOne(countOne + 1)} name=”button1″ />
    <Button handleClick={() => setCountTwo(countTwo + 1)} name=”button1″ />
    </>
    )
    }
    import { useCallback, useState } from 'react'
    const Button = ({handleClick, name}) => {
    console.log(`${name} rendered`)
    return <button onClick={handleClick}>{name}</button>
    }
    const Counter = () => {
    console.log('counter rendered')
    const [countOne, setCountOne] = useState(0)
    const [countTwo, setCountTwo] = useState(0)
    return (
    <>
    {countOne} {countTwo}
    <Button handleClick={() => setCountOne(countOne + 1)} name="button1" />
    <Button handleClick={() => setCountTwo(countTwo + 1)} name="button1" />
    </>
    )
    }

    在此示例中,无论何时单击任一按钮,您都会在控制台中看到:

    // counter rendered
    // button1 rendered
    // button2 rendered
    // counter rendered
    // button1 rendered
    // button2 rendered
    // counter rendered
    // button1 rendered
    // button2 rendered

    现在,如果我们应用useCallback到我们的handleClick函数并将我们的Button包装在 中React.memo,我们可以看到useCallback为我们提供了什么。React.memo类似于useMemo并且允许我们记忆一个组件。

    import { useCallback, useState } from ‘react’
    const Button = React.memo(({handleClick, name}) => {
    console.log(`${name} rendered`)
    return <button onClick={handleClick}>{name}</button>
    })
    const Counter = () => {
    console.log(‘counter rendered’)
    const [countOne, setCountOne] = useState(0)
    const [countTwo, setCountTwo] = useState(0)
    const memoizedSetCountOne = useCallback(() => setCountOne(countOne + 1), [countOne)
    const memoizedSetCountTwo = useCallback(() => setCountTwo(countTwo + 1), [countTwo])
    return (
    <>
    {countOne} {countTwo}
    <Button handleClick={memoizedSetCountOne} name=“button1” />
    <Button handleClick={memoizedSetCountTwo} name=“button1” />
    </>
    )
    }
    import { useCallback, useState } from ‘react’
    const Button = React.memo(({handleClick, name}) => {
    console.log(`${name} rendered`)
    return <button onClick={handleClick}>{name}</button>
    })
    const Counter = () => {
    console.log(‘counter rendered’)
    const [countOne, setCountOne] = useState(0)
    const [countTwo, setCountTwo] = useState(0)
    const memoizedSetCountOne = useCallback(() => setCountOne(countOne + 1), [countOne)
    const memoizedSetCountTwo = useCallback(() => setCountTwo(countTwo + 1), [countTwo])
    return (
    <>
    {countOne} {countTwo}
    <Button handleClick={memoizedSetCountOne} name=”button1″ />
    <Button handleClick={memoizedSetCountTwo} name=”button1″ />
    </>
    )
    }
    import { useCallback, useState } from 'react'
    const Button = React.memo(({handleClick, name}) => {
    console.log(`${name} rendered`)
    return <button onClick={handleClick}>{name}</button>
    })
    const Counter = () => {
    console.log('counter rendered')
    const [countOne, setCountOne] = useState(0)
    const [countTwo, setCountTwo] = useState(0)
    const memoizedSetCountOne = useCallback(() => setCountOne(countOne + 1), [countOne)
    const memoizedSetCountTwo = useCallback(() => setCountTwo(countTwo + 1), [countTwo])
    return (
    <>
    {countOne} {countTwo}
    <Button handleClick={memoizedSetCountOne} name="button1" />
    <Button handleClick={memoizedSetCountTwo} name="button1" />
    </>
    )
    }

    现在,当我们单击任一按钮时,我们只会看到我们单击

  • WordPress React开发项目初学者指南

    WordPress React开发项目初学者指南

    WordPress是一个功能强大的内容管理系统 (CMS),可让您构建从简单网站到复杂复杂的电子商务商店的所有内容。要将平台的PHP代码与JavaScript集成,您可以利用WP REST API和WordPress React

    React由Facebook开发,是一个用户界面 (UI)库,它使用一种简单的、基于组件的方法来构建易于理解的可扩展、跨平台的应用程序。但是,重要的是要学习如何正确使用它以充分利用其特性和功能。

    在本指南中,我们将解释如何在WordPress中使用React。我们将讨论什么是框架,概述它的好处,并向您展示如何使用它。

    React简介

    在开始之前,我们首先要问一个问题,“什么是React?” . 也称为 ReactJS,它是可用于Web开发的最流行的JavaScript库之一。

    React官网

    它由Facebook创建和维护,包含大量可用于构建UI组件的JavaScript代码片段。

    与流行的看法相反,ReactJS不是一个JavaScript框架,因为它只呈现应用程序视图层的组件。因此,如果您正在寻找更复杂的功能,可以将其与Vue.js等实际框架配对。

    同样重要的是要注意有ReactJS和React Native。后者是基于React库构建的开源JavaScript框架。您可以使用它为iOS和Android创建跨平台应用程序和特定于平台的组件。

    React特性和功能

    要了解React的好处,了解它的工作原理会很有帮助。以下是它的一些最重要的特性和功能:

    JSX

    React中使用的主要JavaScript语法扩展是JSX。您可以使用它在JavaScript对象中嵌入HTML代码并简化复杂的代码结构。

    JSX还通过使第三方难以通过未明确写入应用程序的用户输入注入额外代码来帮助防止跨站点脚本 (XSS) 攻击。

    JSX标记包括名称、子项和属性。一个典型的HTML图像标签看起来像这样:

    < img class = “” src= “” alt= “” >
    < img class = “” src= “” alt= “” >
    < img class = "" src= "" alt= "" >

    但是,一个JSX标记应该如下所示:

    < img className= “” src= “” alt= “” / >
    < img className= “” src= “” alt= “” / >
    < img className= "" src= "" alt= "" / >

    此外,数值写在大括号内。与JavaScript类似,引号代表字符串:

    const name = ‘John Doe’;
    const element = <h1>Hello, {name}</h1>;
    ReactDOM.render(
    element,
    document.getElementById(‘root’)
    );
    const name = ‘John Doe’;
    const element = <h1>Hello, {name}</h1>;
    ReactDOM.render(
    element,
    document.getElementById(‘root’)
    );
    const name = 'John Doe’;
    const element = <h1>Hello, {name}</h1>;
    ReactDOM.render(
      element,
      document.getElementById('root')
    );

    您可以将任何有效的JavaScript表达式放在大括号内。例如,它可以是“user.firstName”或“formatName(user)”。

    虚拟DOM

    文档对象模型 (DOM)以数据树结构呈现网页,React将其存储在其内存中。React可以实现对树的某些部分的更新,而不是完全重新渲染它。

    Virtual DOM提供单向数据绑定。这使得操作和更新它比原始DOM更快。

    它使用称为差异的过程。这是React生成一个新的Virtual DOM树,将其与旧的比较,然后找到将更改应用到真实 DOM 的最有效方法的时候。这需要更少的时间和更少的资源,这对于涉及大量用户交互的大型项目是有益的。

    DOM还支持声明式API。这意味着您可以告诉React您希望UI处于哪种状态,以确保DOM将匹配该状态。

    组件

    正如我们所提到的,React组件是构成UI的独立、可重用的代码片段。这些组件的工作方式类似于JavaScript函数。他们接受道具,这是任意输入。当一个函数组件返回一个元素时,它会影响UI的外观。

    Props是只读的。这是一个例子:

    import React, { useState } from ‘react’
    import ReactDOM from ‘react-dom’
    const ParentComponent = () => {
    const [stateVariable, setStateVariable] = useState(‘this is the starting value for the variable’);
    return (
    <div>
    <h1>This is a function component view</h1>
    <ChildComponent exampleProp={stateVariable} />
    </div>
    )
    }
    const ChildComponent = (props) => {
    return (
    <div>
    <h2>{props.exampleProp}</h2>
    </div>
    )
    }
    ReactDOM.render( <ParentComponent />, document.getElementById(‘app’) );
    import React, { useState } from ‘react’
    import ReactDOM from ‘react-dom’

    const ParentComponent = () => {
    const [stateVariable, setStateVariable] = useState(‘this is the starting value for the variable’);

    return (
    <div>
    <h1>This is a function component view</h1>
    <ChildComponent exampleProp={stateVariable} />
    </div>
    )
    }

    const ChildComponent = (props) => {
    return (
    <div>
    <h2>{props.exampleProp}</h2>
    </div>
    )
    }

    ReactDOM.render( <ParentComponent />, document.getElementById(‘app’) );

    import React, { useState } from 'react' 
    import ReactDOM from 'react-dom' 
     
    const ParentComponent = () => { 
        const [stateVariable, setStateVariable] = useState('this is the starting value for the variable'); 
     
        return ( 
            <div> 
                <h1>This is a function component view</h1>
                <ChildComponent exampleProp={stateVariable} />
            </div> 
        ) 
    } 
     
    const ChildComponent = (props) => {
        return (
            <div>
                <h2>{props.exampleProp}</h2>
            </div>
        )
    }
     
     
    ReactDOM.render( <ParentComponent />, document.getElementById('app') );

    有两种主要类型——组件函数组件。类组件使用生命周期WordPress钩子和API调用:

    class ExampleComponent extends React.Component {
    constructor(props) {
    super(props);
    this.state = { };
    }
    render() {
    return (
    <div>
    <h1>This is a view created by a class component</h1>
    </div>
    );
    }
    }
    class ExampleComponent extends React.Component {
    constructor(props) {
    super(props);
    this.state = { };
    }
    render() {
    return (
    <div>
    <h1>This is a view created by a class component</h1>
    </div>
    );
    }
    }
    class ExampleComponent extends React.Component {
      constructor(props) {
        super(props);
        this.state = { };
      }
      render() {
        return (
          <div>
            <h1>This is a view created by a class component</h1>
          </div>
        );
      }
    }

    同时,一个功能组件看起来像下面的例子:

    const ExampleComponent = (props) => {
    const [stateVariable, setStateVariable] = useState();
    return (
    <div>
    <h1>This is a function component view</h1>
    </div>
    )
    }
    const ExampleComponent = (props) => {
    const [stateVariable, setStateVariable] = useState(”);
    return (
    <div>
    <h1>This is a function component view</h1>
    </div>
    )
    }
    const ExampleComponent = (props) => {
        const [stateVariable, setStateVariable] = useState('');
        return (
            <div>
                <h1>This is a function component view</h1>
            </div>
        )
    }

    功能组件用于在没有数据请求或状态管理的情况下呈现视图。

    状态

    State指的是React组件的内置对象。这是您存储元素属性值的地方。如果状态改变,组件会重新渲染。

    状态管理是管理这些应用程序状态并将数据存储在状态管理库中的过程。你可以使用一些状态管理库,包括ReduxRecoil,后者对初学者更友好。

    为什么要使用React?

    使用React进行WordPress开发有很多好处。对于初学者来说,它对初学者很友好,许多网络托管服务提供商都支持它的使用。

    由于它依赖于纯JavaScript和组件,因此您只需学习几天即可使用它来创建基于Web的应用程序。还有很多网站可以学习如何免费在线编码。对JavaScript基础知识的扎实理解可以简化该过程。

    React的另一个好处是它允许您在其他应用程序中重用组件。它是开源的,因此您可以预先构建您的组件并将它们嵌套在其他组件之间,而不会使您的代码臃肿。

    由于JSX集成,React组件的编写也相对简单,我们稍后会讨论。您可以合并HTML排版、标签并利用多种功能呈现来进行动态应用程序开发。

    借助React,您还可以使用官方命令行界面 (CLI) – Create React App – 来加快单页应用程序的开发。它带有预配置的工具,可以帮助您简化设置和学习过程。

    最后,React也是SEO友好的。虚拟DOM实现有助于提高页面速度、提高性能和服务器端渲染,使机器人更容易抓取您的网站。

    WP REST API概述

    WordPress REST应用程序接口 (API)使开发人员能够将JavaScript框架(例如React)与WordPress集成。您可以从站点的前端访问WP REST API,添加自定义文章类型,并构建由该API支持的React应用程序。

    WP REST API是一组用于构建软件应用程序的协议。它们定义了程序之间如何共享信息和数据以及它们的组件如何交互。REST是Representational State Transfer的缩写,指的是程序的风格定义架构约束。

    应用程序读取的结构化数据格式称为JavaScript Object Notation (JSON)。它有助于简化WordPress与其他应用程序和程序之间的通信。

    WP REST API产生了一个解耦环境,允许用户将WordPress视为无头CMS。这意味着可以使用多种前端框架来钩住WordPress的后端。这对于不太热衷于PHP的开发人员来说是有利的。

    React——开始之前

    JavaScript、CSS和HTML的基本知识将有助于学习React。此外,如果您熟悉ECMAScript 6(也称为 ES6)、函数式编程和面向对象编程,学习过程会更加高效。

    在程序方面,您还需要在计算机上安装一些依赖项。这包括NodeJSnpm以及一个文本编辑器。或者,您可能还想使用Git进行版本控制。

    为WordPress开发React项目最流行的方法是使用Create React App

    Create React App

    CRA提供了一个简单的环境来学习React并使用它来构建单页应用程序。请注意,为了使用它,您首先需要在您的设备上安装Node和npm。

    要创建一个新项目,您可以在终端中运行以下命令:

    npx create-react-app wp-react-demo
    npx create-react-app wp-react-demo
    npx create-react-app wp-react-demo
    

    如果您还没有这样做,它将确认您要在创建演示之前安装Create React App。这使样板模板。你也可以用你自己的名字替换“wp-react-demo”。

    接下来,运行以下命令:

    cd wp-react-demo
    npm start
    cd wp-react-demo
    npm start
    cd wp-react-demo
    npm start

    目录结构将如下所示:

    ├── README.md
    ├── package.json
    ├── public
    │ ├── favicon.ico
    │ ├── index.html
    │ └── manifest.json
    ├── src
    │ ├── App.css
    │ ├── App.js
    │ ├── App.test.js
    │ ├── index.css
    │ ├── index.js
    │ ├── logo.svg
    │ └── registerServiceWorker.js
    ├── README.md
    ├── package.json
    ├── public
    │ ├── favicon.ico
    │ ├── index.html
    │ └── manifest.json
    ├── src
    │ ├── App.css
    │ ├── App.js
    │ ├── App.test.js
    │ ├── index.css
    │ ├── index.js
    │ ├── logo.svg
    │ └── registerServiceWorker.js
    ├── README.md
    ├── package.json
    ├── public
    │ ├── favicon.ico
    │ ├── index.html
    │ └── manifest.json
    ├── src
    │ ├── App.css
    │ ├── App.js
    │ ├── App.test.js
    │ ├── index.css
    │ ├── index