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>
    )
}

效果

相关推荐
whatever who cares1 小时前
大型 React 项目的文件结构
前端·react.js·前端框架
假如让我当三天老蒯2 小时前
useCallback 详细解释(从原理到用法)(自学用)
前端·react.js
Vu4612 小时前
nextjs的图片和文字优化
react.js
gogoing5 小时前
React Hooks 完整指南
react.js
假如让我当三天老蒯6 小时前
State和Props区别和左右(自学用)
前端·react.js
夜雪闻竹7 小时前
React Query + REST API 最佳实践
前端·react.js·前端框架
戈德斯文9 小时前
我做了一面互联网摸鱼墙:从无限 Canvas 到本地生产环境
react.js·canvas·next.js
vim怎么退出1 天前
Dive into React——Hooks 原理
react.js·源码阅读
光影少年1 天前
react的useMemo 如何优化?
前端·react.js·掘金·金石计划