自定义hook

2022-11-06  本文已影响0人  未路过

多个组件有相同的逻辑的时候,可以把他抽取到一个独立的hook里面。
自定义hook的本质就是函数代码的抽取,他本身不算是react的特性。
自定义hook的要求是函数的名字必须以use开头

练习1

image.png
import React, { memo, useEffect, useState } from "react";

function useLogLife(cName) {
  useEffect(() => {
    console.log(cName + "组件被创建");
    return () => {
      console.log(cName + "组件被销毁");
    };
  }, []);
}
const Home = memo(() => {
  useLogLife("home");

  return <h1>Home Page</h1>;
});

const About = memo(() => {
  useLogLife("about");

  return <h1>About Page</h1>;
});
const App = memo(() => {
  const [isShow, setIsShow] = useState(true);

  useLogLife("app");
  return (
    <div>
      {isShow && <Home />}
      {isShow && <About />}
      <button onClick={(e) => setIsShow(!isShow)}>切换</button>
    </div>
  );
});

export default App;
/* 

home组件被创建
about组件被创建
app组件被创建
*/

练习2

image.png
import React, { memo } from 'react'
import { useUserToken } from "./hooks"

// User/Token

const Home = memo(() => {
  const [user, token] = useUserToken()

  return <h1>Home Page: {user.name}-{token}</h1>
})

const About = memo(() => {
  const [user, token] = useUserToken()

  return <h1>About Page: {user.name}-{token}</h1>
})

const App = memo(() => {
  return (
    <div>
      <h1>App Root Component</h1>
      <Home/>
      <About/>
    </div>
  )
})

export default App
import { useContext } from "react"
import { UserContext, TokenContext } from "../context"

function useUserToken() {
  const user = useContext(UserContext)
  const token = useContext(TokenContext)

  return [user, token]
}

export default useUserToken

练习3

监听窗口滚动

import { useState, useEffect } from "react";

function useScrollPosition() {
  const [scrollX, setScrollX] = useState(0);
  const [scrollY, setScrollY] = useState(0);

  useEffect(() => {
    function handleScroll() {
      // console.log(window.scrollX, window.scrollY)
      //window和document的区别是,window发生滚轮事件,会传递给document,所以document也会拿到,
      setScrollX(window.scrollX);
      setScrollY(window.scrollY);
    }

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

  return [scrollX, scrollY];
}

export default useScrollPosition;

import React, { memo } from 'react'
import { useUserToken } from "./hooks"

// User/Token

const Home = memo(() => {
  const [user, token] = useUserToken()

  return <h1>Home Page: {user.name}-{token}</h1>
})

const About = memo(() => {
  const [user, token] = useUserToken()

  return <h1>About Page: {user.name}-{token}</h1>
})

const App = memo(() => {
  return (
    <div>
      <h1>App Root Component</h1>
      <Home/>
      <About/>
    </div>
  )
})

export default App

练习4

image.png
import { useEffect } from "react"
import { useState } from "react"

function useLocalStorage(key) {
  // 1.从localStorage中获取数据, 并且数据数据创建组件的state
  const [data, setData] = useState(() => {
    const item = localStorage.getItem(key)
    if (!item) return ""
    return JSON.parse(item)
  })

  // 2.监听data改变, 一旦发生改变就存储data最新值
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(data))
  }, [data])

  // 3.将data/setData的操作返回给组件, 让组件可以使用和修改值
  return [data, setData]
}


export default useLocalStorage
import React, { memo } from 'react'
import { useEffect } from 'react'
import { useState } from 'react'
import useLocalStorage from './hooks/useLocalStorage'

const App = memo(() => {
  // 通过key, 直接从localStorage中获取一个数据
  // const [token, setToken] = useState(localStorage.getItem("token"))
  // useEffect(() => {
  //   localStorage.setItem("token", token)
  // }, [token])
  const [token, setToken] = useLocalStorage("token")
  function setTokenHandle() {
    setToken("james")
  }

  // const [avatarUrl, setAvatarUrl] = useState(localStorage.getItem("avatarUrl"))
  // useEffect(() => {
  //   localStorage.setItem("avatarUrl", avatarUrl)
  // }, [avatarUrl])
  const [avatarUrl, setAvatarUrl] = useLocalStorage("avatarUrl")
  function setAvatarUrlHandle() {
    setAvatarUrl("http://www.james.com/cba.png")
  }

  return (
    <div className='app'>
      <h1>App Root Component: {token}</h1>
      <button onClick={setTokenHandle}>设置token</button>
      <h1>avatarURL: {avatarUrl}</h1>
      <button onClick={setAvatarUrlHandle}>设置新头像地址</button>
    </div>
  )
})

export default App
上一篇 下一篇

猜你喜欢

热点阅读