react18之08自定义hook (简单的axios-get、修改浏览器title、localStorage、获取滚动条位置、img转换为base64)

目录

  • react18之自定义hook ()
    • [01:自定义一个 简单的axios hook 发起get请求](#01:自定义一个 简单的axios hook 发起get请求)
    • [02:自定义一个 修改浏览器title hook](#02:自定义一个 修改浏览器title hook)
    • [03:自定义一个 localStorage(获取、存储、移除) hook](#03:自定义一个 localStorage(获取、存储、移除) hook)
    • [04:自定义一个 useScrollPosition(获取当前滚动条的位置) hook](#04:自定义一个 useScrollPosition(获取当前滚动条的位置) hook)
    • [05:自定义一个 useImageToBase64(img转换为base64) hook](#05:自定义一个 useImageToBase64(img转换为base64) hook)

react18之自定义hook ()

  • hook的使用规则
    • 自定义hook本质而言就是一个函数,也就是抽离公共部门的代码,类似抽离组件或者说mixin(vue中的mixin)。
    • hook必须以use开头(不遵循的话,由于无法判断某个函数是否包含对其内部 Hook 的调用,React 将无法自动检查你的 Hook 是否违反了 Hook 的规则)
    • 内部正常使用useState useEffect或者其他hooks
    • 自定义返回结果,格式不限
    • 在两个组件中使用相同的 Hook 不会共享 state(自定义 Hook 是一种重用状态逻辑的机制(例如设置为订阅并存储当前值),所以每次使用自定义 Hook 时,其中的所有 state 和副作用都是完全隔离的。)
    • 每次调用 Hook,它都会获取独立的 state(从 React 的角度来看,我们的组件只是调用了 useState 和 useEffect,一个组件中可以调用多次useState和useEffect,它们都是完全独立的)

01:自定义一个 简单的axios hook 发起get请求

  • npm i axios

useHttp.jsx

js 复制代码
import { useState, useEffect } from "react";
import axios from "axios";
export default function UseHttp(props) {
  const { url } = props;
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    setLoading(true);
    axios.get(url)
      .then((res) => {
        setData(res);
      })
      .catch((err) => {
        setError(err);
      })
      .finally(() => {
        setLoading(false);
      });
  }, [url]);
  return [loading, data, error];
}

使用useHttp hook

js 复制代码
import React, { useState,useEffect } from 'react';
import UseHttp from './useHttp';
export default function Base(props) {
    const [list,setList] = useState([])
    const url = 'http://localhost:9999' + '/list'
    const [loading,data,error] = UseHttp({url})
    useEffect(()=>{
      if ( data && data.status === 200) {
        setList(data.data)
      }
    },[data])

    return (
        <div className='content'>
          {
            loading ? '加载中' : 
            <>
             { error ? <div>error</div> :
              <div>
                {
                  list.map(item=>{
                    return (
                      <div key={item.id}>
                        name-{ item.name};
                        age- { item.age }
                      </div>
                    )
                  })
                }
              </div>}
            </>
          }
        </div>
    )
}

效果

02:自定义一个 修改浏览器title hook

js 复制代码
import { useEffect } from 'react';

export default function useTitle(props) {
    const {title} = props

    useEffect(() => {
        document.title = title
        // 组件卸载时,恢复默认标题
        return () => {
          document.title = 'Original Title';
        };
    }, [title])

    return { title }
}

03:自定义一个 localStorage(获取、存储、移除) hook

useLocalStorage.jsx

js 复制代码
import { useState, useEffect } from 'react';

const useLocalStorage = (key, initialValue) => {
  // 根据key获取localStorage的数据,若是有数据则返回,没有则返回初始化设置的值
  const [data, setData] = useState(() => {
    let storageVal = localStorage.getItem(key);
    return (storageVal && storageVal !== 'undefined') ? JSON.parse(storageVal) : initialValue;
  });

  // 若是数据有变化 则存储数据
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(data));
  }, [key, data]);

  const removeLocalStorage = () => {
    setData(initialValue);
    localStorage.removeItem(key);
  };

  return [data, setData, removeLocalStorage];
};

export default useLocalStorage;

使用hook

js 复制代码
import React, { useState, useEffect } from 'react';
import useLocalStorage from './useLocalStorage';
export default function Base(props) {
    const [name,setName,removeLocalStorage]= useLocalStorage('name','')
    function getName(){
      console.log('name',name);
    }
    function setLocalName(){
      setName('我是setName')
    }
    function delLocalName(){
      removeLocalStorage('name')
    }
    return (
        <div className='content'>
          <div>
            <div>name-{name}</div>
            <div>获取name数据 - <button onClick={getName}>getName</button></div>
            <div>设置name数据 - <button onClick={setLocalName}>setName</button></div>
            <div>移除name数据 - <button onClick={delLocalName}>delName</button></div>
          </div>
        </div>
    )
}

效果

04:自定义一个 useScrollPosition(获取当前滚动条的位置) hook

useScrollPosition.jsx

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

  useEffect(() => {
    const handleScroll = () => {
      let scrollY = window.scrollY ? Math.round(window.scrollY) : 0
      setScrollPosition(scrollY);
    }
    document.addEventListener("scroll", handleScroll);

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

  return scrollPosition;
}

export default useScrollPosition;

使用

js 复制代码
   const scrollPosition = useScrollPosition()
   console.log('scrollPosition', scrollPosition);

效果

05:自定义一个 useImageToBase64(img转换为base64) hook

useImageToBase64.jsx

js 复制代码
import React, { useState } from 'react';

const useImageToBase64 = () => {
  const [base64Image, setBase64Image] = useState(null);

  const imageToBase64 = (file) => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();

      reader.onload = () => {
        resolve(reader.result);
      };

      reader.onerror = (error) => {
        reject(error);
      };

      reader.readAsDataURL(file);
    });
  };

  const handleImageUpload = (event) => {
    const file = event.target.files[0];
    if (file) {
      imageToBase64(file)
        .then((base64) => {
          setBase64Image(base64);
        })
        .catch((error) => {
          console.error('Error converting image to Base64:', error);
        });
    }
  };

  return { base64Image, handleImageUpload };
};

export default useImageToBase64;

使用

js 复制代码
import React from 'react';
import useImageToBase64 from "../自定义hook/useImageToBase64 "
export default function Test(props) {
  const { base64Image, handleImageUpload } = useImageToBase64();
  console.log('base64Image',base64Image);
    return (
        <div className='content' style={{marginTop:'40px'}}>
          Test
          <div>
            <input type="file" accept="image/*" onChange={handleImageUpload} />
            {base64Image && <img src={base64Image} alt="Uploaded" />}
          </div>
        </div>
    )
}

效果

相关推荐
Eloudy3 小时前
ReAct 原理简介
前端·javascript·人工智能·react.js·agent·gpu
嘟嘟07175 小时前
Next.js 博客左侧笔记列表是怎么从 Redis 渲染出来的?从组件、children 到动态路由一次讲清
redis·react.js·前端工程化
张元清6 小时前
React useInterval Hook:没有过期闭包的 setInterval (2026)
javascript·react.js
MXN_小南学前端6 小时前
React超长文本域中实现“返回顶部”浮动按钮
前端·javascript·react.js
YIAN11 小时前
http无状态?State来展示!从基础路由到鉴权守卫,吃透 SPA 前端路由核心
前端·react.js
console.log('npc')13 小时前
React 19 + Vite 企业级前端项目:从零搭建到规范交付
前端·react.js·前端框架
光影少年13 小时前
react离线缓存、图片缓存方案
开发语言·前端·javascript·react native·react.js·缓存·前端框架
抱抱宝1 天前
Agent-study项目教程(03):手写 Mini-ReAct Agent(不依赖框架)
javascript·人工智能·gpt·react.js·prompt·agent
想要成为糕糕手1 天前
🚀 在浏览器里跑 DeepSeek-R1?WebGPU 端侧推理实战(六)—— 完结篇:消息渲染与流式收尾
react.js·typescript·llm
YIAN1 天前
从 Hash 底层原理到 React Router v6 实战:我学会了什么?
前端·react.js·vue-router