Typescript和React造轮子一之React hook基础(二)

本文目录

        • 1、hook
          • 1-1、useEffect
          • 1-2、useRef与useContext
          • 1-3、 forwardRef
          • 1-4、useRef
          • 1-5、useRequest
          • 1-6、useCreation
          • 1-7、useMemo和 useCallback
        • 2、组件之间的传值
        • 3、自定义hook实现
        • 4、hook中网络请求数据

第一个简单组件hello word

import React, { useContext } from 'react'
import { ThemeContext } from '../App'
interface IHelloProps {
  message?: string;
}

const Hello: React.FC = (props) => {
  const theme = useContext(ThemeContext)
  console.log(theme)
  const style = {
    background: theme.background,
    color: theme.color,
  }
  return 

{props.message}

} Hello.defaultProps = { message: "Hello World" } export default Hello
1、hook

钩子是允许从功能组件(function component)“挂钩”React状态和生命周期功能的功能。钩子在类内部不起作用 - 它们允许你在没有类的情况下使用React。

useState简单实例

import { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    

You clicked {count} times

); }
1-1、useEffect

Effect Hook中的useEffect增加了在功能组件执行副作用的功能。它与React类中的componentDidMount,componentDidUpdate和componentWillUnmount具有相同的用途,但统一为单个API。
简单实例:

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

const MouseTracker: React.FC = () => {
  const [ positions, setPositions ] = useState({x: 0, y: 0})
  useEffect(() => {
    console.log('add effect', positions.x)
    const updateMouse= (e: MouseEvent) => {
      console.log('inner')
      setPositions({ x: e.clientX, y: e.clientY })
    }
    document.addEventListener('click', updateMouse)
    return () => {
      console.log('remove effect', positions.x)
      document.removeEventListener('click', updateMouse)
    }
  }, [])
  console.log('before render', positions.x)
  return (
    

X: {positions.x}, Y : {positions.y}

) } export default MouseTracker

useEffect不过不传递第二个参数在页面每次重新渲染时都会调用,这里第二个参数传入空数组的意思是只有在页面出现或者卸载时执行.如果传入其他变量则执行与否只依赖该变量是否变化.

不同组件之间共享hook封装

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

const useMousePosition = () => {
  const [ positions, setPositions ] = useState({x: 0, y: 0})
  useEffect(() => {
    console.log('add effect', positions.x)
    const updateMouse= (e: MouseEvent) => {
      setPositions({ x: e.clientX, y: e.clientY })
    }
    document.addEventListener('mousemove', updateMouse)
    return () => {
      console.log('remove effect', positions.x)
      document.removeEventListener('mousemove', updateMouse)
    }
  }, [])
  return positions
}

export default useMousePosition

定义后在其他组件中引入就可共用状态

const positons = useMousePosition();

自定义hook
在react hook中我们可以把一些天然逻辑重复的业务抽离出来,下面看下例子:
定义文件useURLLoader.tsx

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

const useURLLoader = (url: string, deps: any[] = []) => {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(false)
  useEffect(() => {
    setLoading(true)
    axios.get(url).then(result => {
      setData(result.data)
      setLoading(false)
    })
  }, deps)
  return [data, loading]
}

export default useURLLoader

使用

interface IShowResult {
  message: string;
  status: string;
}

const App: React.FC = () => {
     const [show, setShow] = userState(true)
     const [data, loadin] = userState(true) = useURLLoader('https://dog.ceo/api/breeds/imagte', show)
     const dogResult = data as IShowResult 
    return (
        
{loading ?

读取中

: }
) }
1-2、useRef与useContext

Typescript和React造轮子一之React hook基础(二)_第1张图片
Typescript和React造轮子一之React hook基础(二)_第2张图片

App.tsx文件

import React, { useState } from 'react';
import './App.css';
import LikeButton from './components/LikeButton'

interface IThemeProps {
  [key: string]: {color: string; background: string;}
}
const themes: IThemeProps = {
 'light': {
   color: '#000',
   background: '#eee',
 },
 'dark': {
    color: '#fff',
    background: '#222',
  }
}
export const ThemeContext = React.createContext(themes.light)
const App: React.FC = () => {
  const [ show, setShow ] = useState(true)
  return (
    
); } export default App;

LikeButton.tsx文件

import React, { useState, useEffect, useRef, useContext } from 'react'
import { ThemeContext } from '../App'
const LikeButton: React.FC = () => {
  const [like, setLike] = useState(0)
  const likeRef = useRef(0)
  const didMountRef = useRef(false)
  const domRef = useRef(null)
  const theme = useContext(ThemeContext)
  console.log(theme)
  const style = {
    background: theme.background,
    color: theme.color,
  }
  useEffect(() => {
    console.log('document title effect is running')
    document.title = `点击了${like}次`
  }, [like])
  useEffect(() => {
    if (didMountRef.current) {
      console.log('this is updated')
    } else {
      didMountRef.current = true
    }
  })
  useEffect(() => {
    if (domRef && domRef.current) {
      domRef.current.focus()
    }
  })
  function handleAlertClick() {
    setTimeout(() => {
      alert('you clicked on ' + likeRef.current)
    }, 3000)
  }
  return (
    <>
    
    
    
    
  )
}
export default LikeButton
1-3、 forwardRef

引用传递(Ref forwading)是一种通过组件向子组件自动传递 引用ref 的技术。

import React, { Component, createRef, forwardRef } from 'react';

const FocusInput = forwardRef((props, ref) => (
    
));

class ForwardRef extends Component {
    constructor(props) {
        super(props);
        this.ref = createRef();
    }

    componentDidMount() {
        const { current } = this.ref;
        current.focus();
    }

    render() {
        return (
            

forward ref

); } } export default ForwardRef;
1-4、useRef
const refContainer = useRef(initialValue);

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内持续存在。

一个常见的用例便是命令式地访问子组件:

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    inputEl.current.focus();
  };
  return (
    <>
      
      
    
  );
}

useRef和createRef的区别

1-5、useRequest
import { useRequest } from '@umijs/hooks';

function getUsername() {
  return Promise.resolve('jack');
}

export default () => {
  const { data, error, loading } = useRequest(getUsername)
  
  if (error) return 
failed to load
if (loading) return
loading...
return
Username: {data}
}

这是一个最简单的网络请求示例。在这个例子中 useRequest 接收了一个 Promise 函数。在组件初始化时,会自动触发 getUsername 执行,并自动管理 data 、 loading 、 error 等数据,我们只需要根据状态来写相应的 UI 实现即可。
useRequest教程

1-6、useCreation

1、确定输入输出,useCreation接受两个参数,一个工厂函数,一个依赖项数组,并返回工厂函数执行后的结果
Typescript和React造轮子一之React hook基础(二)_第3张图片

1-7、useMemo和 useCallback

一篇文章带你理解 React 中最“臭名昭著”的 useMemo 和 useCallback

2、组件之间的传值

参考
父组件

import { useCallback, useEffect, useState, useRef } from "react";
import Header from "../../components/header/index";
import Footer from "../../components/footer/index";
import Changefather from "./components/changefather";

const Home = () => {
  const [sisters, setsisters] = useState("村里一朵花");
  const [loding, setloding] = useState(false); //loding;
  const [childData, setChildData]: any = useState(); //获取子组件的值
  const childMethodRef:any = useRef();
  const changeloding = () => {
    setloding(true);
    setTimeout(() => {
      setloding(false);
    }, 1000);
  };
  const handleChildFun = () => {
    childMethodRef.current.fun2()
  };
  const getchildfn = useCallback((data: any) => {
    setChildData(data);
  }, []);
  return (
    
这是一个小小的button
{
这是子组件的值{childData}
}
{ handleChildFun(); }} > 我要
); }; export default Home;

子组件

import{ useEffect, useState ,useImperativeHandle,forwardRef} from "react";
import Countdown from "react-countdown";
import dayjs from "dayjs";

interface sister {
  sisters: string;
  setsisters: any;
  handleChildData:any;
  cRef:any
}
let Changeyears = (props: sister):any => {
  const { sisters, setsisters,handleChildData,cRef } = props;
  const [Cdtime,setCdtime]=useState(dayjs(1649999957832).valueOf())
  const [childtext , setchildtext ] = useState('')
  useImperativeHandle(cRef, () => ({
    childFun (info: any) {
    console.log(info)
    },
    fun2(){
    console.log('fun2')
    }
    }));
  useEffect(()=>{
    handleChildData(childtext)
  },[childtext])
  return (
    <>
       {
         const {days,hours,minutes,seconds} = time.formatted
         return (
           
还有{days}天{hours}时{minutes}分{seconds}秒
) }} />
{ setchildtext('今天给爸爸洗脚') }}>传给父组件值
{ setchildtext('今天不给爸爸洗脚') }}> 第二次传给父组件的值
{sisters}
); }; Changeyears = forwardRef(Changeyears); export default Changeyears;

Typescript和React造轮子一之React hook基础(二)_第4张图片

import React, { useRef, useImperativeHandle } from 'react';
import ReactDOM from 'react-dom';

const FancyInput = React.forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));

  return 
});

const App = props => {
  const fancyInputRef = useRef();

  return (
    
) } ReactDOM.render(, root);
3、自定义hook实现
import React,{Component,useState} from 'react'

function useCountFather(initValue){
  var [count,setCount]=useState(initValue)
  function increase(){
    setCount(++count)
  }
  function decrease(){
    setCount(--count)
  }
  return [count,{increase,decrease}]
}

function Count(){
  var [count,countFatherApi]=useCountFather(0)
  
  return(
    

{count}

) } function App(){ return(
) } export default App;
4、hook中网络请求数据
import React, { useState, useEffect } from 'react';
import axios from 'axios';
 
function App() {
  const [data, setData] = useState({ hits: [] });
 
  useEffect(async () => {
    const result = await axios(
      'https://hn.algolia.com/api/v1/search?query=redux',
    );
 
    setData(result.data);
  });
 
  return (
    
  );
}
 
export default App;


手动触发

function App() {
  const [data, setData] = useState({ hits: [] });
  const [query, setQuery] = useState('redux');
  const [search, setSearch] = useState('');
 
  useEffect(() => {
    const fetchData = async () => {
      const result = await axios(
        `http://hn.algolia.com/api/v1/search?query=${query}`,
      );
 
      setData(result.data);
    };
 
    fetchData();
  }, [query]);
 
  return (
    
       setQuery(event.target.value)}
      />
      
 
      
    
  );
}


参考

你可能感兴趣的:(我的前端,react.js,typescript,javascript)