自定义Hook的学习与使用~~~~~~~~

本文介绍了自定义Hook的基本概念,强调其作为函数代码逻辑抽取的作用。通过实例展示了如何创建自定义Hook,包括组件生命周期的打印、使用User和Token Context、获取窗口滚动位置以及localStorage数据存储。通过自定义Hook,可以减少代码冗余,提高代码复用性和可维护性。

二. 自定义Hook

1. 认识自定义hook

自定义Hook本质上只是一种函数代码逻辑的抽取,严格意义上来说,它本身并不算React的特性。
自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook。

需求:所有的组件在创建和销毁时都进行打印

  • 组件被创建:打印 组件被创建了;
  • 组件被销毁:打印 组件被销毁了;
export default function CustomHookDemo() {
  useEffect(() => {
    console.log("组件被创建了");
    return () => {
      console.log("组件被销毁了");
    }
  }, [])

  return (
    <div>
      <h2>CustomHookDemo</h2>
    </div>
  )
}

但是这样来做意味着所有的组件都需要有对应的逻辑:

function Home(props) {
  useEffect(() => {
    console.log("组件被创建了");
    return () => {
      console.log("组件被销毁了");
    }
  }, [])
  return <h2>Home</h2>
}

function Profile(props) {
  useEffect(() => {
    console.log("组件被创建了");
    return () => {
      console.log("组件被销毁了");
    }
  }, [])
  return <h2>Profile</h2>
}

如何可以对它们的逻辑进行抽取呢?

  • 我们可能希望抽取到一个函数中,普通的函数中不能使用hook;

那么,我们应该如何操作呢?

  • 非常简单,函数以特殊的方式命名,以 use 开头即可,将其变成自定义Hook
function useLoggingLife() {
  useEffect(() => {
    console.log("组件被创建了");
    return () => {
      console.log("组件被销毁了");
    }
  }, [])
}

当然,自定义Hook可以有参数,也可以有返回值:

function useLoggingLife(name) {
  useEffect(() => {
    console.log(`${name}组件被创建了`);
    return () => {
      console.log(`${name}组件被销毁了`);
    }
  }, [])
}

2. 自定义Hook练习

我们通过一些案例来练习一下自定义Hook。

2.1使用User、Token的Context

比如多个组件都需要使用User和Token的Context:

  • 这段代码我们在每次使用user和token时都需要导入对应的Context,并且需要使用两次useContext;
import React, { useContext } from 'react'
import { UserContext, TokenContext } from '../App'

export default function CustomHookContextDemo() {
  const user = useContext(UserContext);
  const token = useContext(TokenContext);

  console.log(user, token);

  return (
    <div>
      <h2>CustomHookContextDemo</h2>
    </div>
  )
}

我们可以抽取到一个自定义Hook中:hooks/user-hook

export default function useUserContext() {
  const user = useContext(UserContext);
  const token = useContext(TokenContext);

  return [user, token];
}


import React, { useContext } from 'react';
import useUserContext from '../hooks/user-hook';

export default function CustomContextShareHook() {
  const [user, token] = useUserContext();
  console.log(user, token);
  
  return (
    <div>
      <h2>CustomContextShareHook</h2>
    </div>
  )
}
2.2获取窗口滚动的位置

在开发中,某些场景我们可能总是希望获取创建滚动的位置:

import React, { useEffect, useState } from 'react'

export default function CustomScrollPositionHook() {

  const [scrollPosition, setScrollPosition] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      setScrollPosition(window.scrollY);
    }
    document.addEventListener("scroll", handleScroll);

    return () => {
      document.removeEventListener("scroll", handleScroll);
    }
  }, [])

  return (
    <div style={{padding: "1000px 0"}}>
      <h2 style={{position: "fixed", top: 0, left: 0}}>CustomScrollPositionHook: {scrollPosition}</h2>
    </div>
  )
}

但是如果每一个组件都有对应这样的一个逻辑,那么就会存在很多的冗余代码:
将其提取出来作为hook:

import { useState, useEffect } from 'react';
function useScrollPosition() {
  const [scrollPosition, setScrollPosition] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      setScrollPosition(window.scrollY);
    }
    document.addEventListener("scroll", handleScroll);

    return () => {
      document.removeEventListener("scroll", handleScroll)
    }
  }, []);

  return scrollPosition;
}

export default useScrollPosition;

调用上面的自定义hook实现

import React, { useEffect, useState } from 'react'
import useScrollPosition from '../hooks/scroll-position-hook'

export default function CustomScrollPositionHook() {
  const position = useScrollPosition();

  return (
    <div style={{padding: "1000px 0"}}>
      <h2 style={{position: "fixed", left: 0, top: 0}}>CustomScrollPositionHook: {position}</h2>
    </div>
  )
}
2.3数据存储的localStorage

在开发中,我们会有一些数据希望通过localStorage进行存储(当然,你可以根据自己的情况选择sessionStorage)

import React, { useState, useEffect } from 'react'

export default function CustomDataStoreHook() {
  const [name, setName] = useState(() => {
    return JSON.parse(window.localStorage.getItem("name"))
  });

  useEffect(() => {
    window.localStorage.setItem("name", JSON.stringify(name));
  }, [name])

  return (
    <div>
      <h2>CustomDataStoreHook: {name}</h2>
      <button onClick={e => setName("gercke")}>设置name</button>
    </div>
  )
}

如果每一个里面都有这样的逻辑,那么代码就会变得非常冗余:
将其提取出来作为hook:

import React,{useState, useEffect} from 'react';
function useLocalStorage(key) {
  const [data, setData] = useState(() => {
    return JSON.parse(window.localStorage.getItem(key))
  });

  useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(data));
  }, [data]);

  return [data, setData];
}

export default useLocalStorage;

调用上面的自定义hook实现

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

import useLocalStorage from '../hooks/local-store-hook';

export default function CustomDataStoreHook() {
  const [name, setName] = useLocalStorage("name");

  return (
    <div>
      <h2>CustomDataStoreHook: {name}</h2>
      <button onClick={e => setName("kobe")}>设置name</button>
    </div>
  )
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值