📜  ReactJS 自定义钩子

📅  最后修改于: 2022-05-13 01:56:23.643000             🧑  作者: Mango

ReactJS 自定义钩子

React.Js 提供了许多可以在 React 应用程序中使用的内置钩子。但除此之外,您还可以制作自己的自定义钩子并在您的应用程序中使用它,从而提高可读性并减少代码量。自定义钩子是普通的 JavaScript 函数,其名称以“use”开头,它们可能会调用其他钩子(内置或自定义)。

需要自定义 Hooks:您应该使用自定义 Hooks 的主要原因是在您的 React 应用程序中维护 DRY(不要重复自己)的概念。例如,假设您有一些使用一些内置钩子的逻辑,并且您需要在多个功能组件中使用该逻辑。因此,有两种方法可供您使用——1) 在每个组件中编写相同的逻辑(这违反了 DRY 的概念)和 2) 创建一个单独的函数,将逻辑包装在其中,然后从这些组件中调用它。第二个选项无疑是更好的选择,因为您只需编写一次逻辑。在这里,您创建的单独函数是自定义挂钩。因此,每当您觉得自己有一个要在多个功能组件中使用的逻辑时(钩子在类组件中不起作用),只需为其创建一个单独的自定义钩子并使用它。

构建自定义钩子:创建自定义钩子与创建名称以“use”开头的 JavaScript函数相同。它可以使用里面的其他钩子,返回任何你想要它返回的东西,把任何东西作为参数。下面示例中的函数“useCustomHook”是一个使用状态变量“counter”的自定义钩子。函数“resetCounter”将计数器的值增加 1,每当计数器的值更新时,传递给 useEffect 钩子的函数就会被调用。该函数执行一些将在多个组件中使用的代码(删除以专注于如何使用自定义挂钩而不是实现逻辑)。这个自定义钩子返回“resetCounter”函数。

文件名-src/useCustomHook.js:

Javascript
import {useState , useEffect} from "react";
  
// Remember to start the name of your custom hook with "use"
function useCustomHook(initializer , componentName){
    const [counter , setCounter] = useState(initializer);
      
    // Increases the value of counter by 1
       function resetCounter(){
        setCounter(counter + 1);
    }
      
  
    useEffect(() => {
        // Some logic that will be used in multiple components
        console.log("The button of the " 
        + componentName + " is clicked "
        + counter + " times.");
    } , [counter , componentName]); 
      
    // Calls the useEffect hook if the counter updates
    return resetCounter;
}
  
export default useCustomHook;


Javascript
import React from "react";
  
// importing the custom hook
import useCustomHook from "../useCustomHook";
  
function FirstComponent(props){
  
    // ClickedButton = resetCounter;
    const clickedButton = useCustomHook(0 , "FirstComponent"); 
      
    return (
        
            

This is the First Component

                     
    ); }    export default FirstComponent;


Javascript
import React from "react";
  
// Importing the custom hook
import useCustomHook from "../useCustomHook";
  
function SecondComponent(props){
  
    // ClickedButton = resetCounter;
    const clickedButton = useCustomHook(0 , "SecondComponent"); 
      
    return (
        
            

This is the Second Component

                     
    ); }    export default SecondComponent;


Javascript
import React from 'react';
import './App.css';
import FirstComponent from './components/FirstComponent';
import SecondComponent from './components/SecondComponent';
  
function App(){ 
    return( 
        
                            
      ); }       export default App;


Javascript
import React , {useState ,useEffect} from "react";
  
function FirstComponent(props){
      
    const [counter , setCounter] = useState(initializer);
      
    // Increases the value of counter by 1
       function resetCounter(){
        setCounter(counter + 1):
    }
      
    useEffect(() => {
        // Some logic 
        console.log(counter);
    } , [counter]);
      
    const clickedButton = resetCounter; 
      
    return (
        
            

This is the First Component

                     
    ); }    export default FirstComponent;


在组件中使用自定义挂钩:要在组件中使用自定义挂钩,只需从“src”文件夹中的“useCustomHook.js”文件中导入“useCustomHook”函数。

文件名-src/components/FirstComponent.js:

Javascript

import React from "react";
  
// importing the custom hook
import useCustomHook from "../useCustomHook";
  
function FirstComponent(props){
  
    // ClickedButton = resetCounter;
    const clickedButton = useCustomHook(0 , "FirstComponent"); 
      
    return (
        
            

This is the First Component

                     
    ); }    export default FirstComponent;

文件名:src/components/SecondComponent.js:

Javascript

import React from "react";
  
// Importing the custom hook
import useCustomHook from "../useCustomHook";
  
function SecondComponent(props){
  
    // ClickedButton = resetCounter;
    const clickedButton = useCustomHook(0 , "SecondComponent"); 
      
    return (
        
            

This is the Second Component

                     
    ); }    export default SecondComponent;

文件名:src/App.js:

Javascript

import React from 'react';
import './App.css';
import FirstComponent from './components/FirstComponent';
import SecondComponent from './components/SecondComponent';
  
function App(){ 
    return( 
        
                            
      ); }       export default App;

输出:

如果您打开浏览器的控制台,您将看到:

请注意,即使我们声明了依赖数组,在第一次渲染之后也会调用 useEfffect。这意味着传递给 useEffect 挂钩的回调函数在第一次渲染之后以及依赖数组中的变量被更新时执行。没有直接的方法可以阻止第一次执行。

现在,如果单击第一个按钮(FirstComponent 的按钮)并检查控制台,您会看到每次单击按钮时,计数器的值都会增加 1,并且更新后的值会打印在控制台上。

如果点击第二个按钮,会和上面的输出类似,仔细查看控制台:

请注意,两个组件的计数器(在“usecustomHook”中定义)是不同的。这两个组件使用两个不同的“计数器”状态变量(参见“useCustomhook.js”),它们不共享状态。因此,在这个 React 应用程序中,每个组件都有自己的“计数器”状态变量。同样,每个组件都有自己的 useEffect 并且它们彼此独立地执行。如果 FirstComponent 的计数器更新,则调用 FirstComponent 的 useEffect,类似地,如果 SecondComponent 的计数器更新,则独立于 FirstComponent 调用 SecondComponent 的 useEffect(参见上面的输出)。

在“ src/components/FirstComponent.js ”中的代码等价于以下代码:

Javascript

import React , {useState ,useEffect} from "react";
  
function FirstComponent(props){
      
    const [counter , setCounter] = useState(initializer);
      
    // Increases the value of counter by 1
       function resetCounter(){
        setCounter(counter + 1):
    }
      
    useEffect(() => {
        // Some logic 
        console.log(counter);
    } , [counter]);
      
    const clickedButton = resetCounter; 
      
    return (
        
            

This is the First Component

                     
    ); }    export default FirstComponent;

注意:以“use”开头的自定义钩子命名很重要,因为没有它,React 无法意识到它是自定义钩子,因此无法将钩子的规则应用于它。所以,你应该以“use”开头来命名它。