React Hook使用说明

React 使用Hook。技术知识点说明

2020-5-18 更新说明

  1. 补充部分hooks使用说明。
  2. 补充功能说明。
说明

在不使用class情况下使用state及其他特性。开始支持版本:React 16.8

使用规则:

  • 只能在函数最外层使用Hook,不能在循环、条件判断或者子函数中使用。
  • 只能在React函数组件中使用Hook
  • 在自定义Hook可以使用。
  • 没有this执行调用;

安装ESline插件以帮助检测不会犯莫名其妙的错误:

npm install eslint-plugin-react-hooks --save-dev
useState

定义state属性。

  1. 基本使用

    说明:

    • useState返回一对值:属性变量、设置属性值得方法。
    • useState接受一个参数作为属性初始值。
    • 不必定义多个单值;可数组、对象定义,在更新时替换更新;
    import React,{useState} from 'react';
    
    function GetStatus(){
    	const [name,setName] = useState("admin");
    	const [hobby,setHobby] = useState(["read","write","listen"]);
    	
    	return (<div>
            <p>{name+":"+props.name}</p>
            <ul>
                {hobby.map(item=>(<li key={item.toString()}>{item}</li>))}
            </ul>
        </div>);	
    }
    
  2. useState接受一个函数,函数的参数为当前的属性值;用以新值建立在旧值得逻辑处理。

    function UserInfo(){
    	let [info,setInfo] = useState({
    		name:“admin”, 
    		age:25
    	});	
    	return (<Input onChange={e=>setInfo(prev=>({...prev,age:e.target.value}))} />);
    }
    
useEffect

class中:componentDidMount/componentDidUpdate/componentWillUnmount三个函数的合成共有功能;
不用声明周期区分调用;而以组件功能区分执行调用;

  1. 基本使用

    说明:

    • 每次重新渲染都会调用useEffect;
    • 可多次调用useEffect以区分注释每个功能、作用;
    • 如果返回一个函数,将会在组件清除时调用。
    • 接受第二个参数[],定义受监控的属性,只有在该属性变化时更新;如果没有指定属性,则再初始时执行一次;
    import React,{useState,useEffect} from 'react';
    
    function GetStatus(){
    	const [name,setName] = useState("admin");
    	// 会打印两次“doing”
    	useEffect(()=>{
            document.title = "Hook";
            setTimeout(()=>{
                setName("test");
            },3000);
            console.log("doing");
        })
        
        // 只会打印一次“doing”
    	useEffect(()=>{
            document.title = "Hook";
            setTimeout(()=>{
                setName("test");
            },3000);
            console.log("doing");
        },[])
        
    	return (<div>
    		<p>{name}</p>
    	</div>);	
    }
    
  2. 返回一个函数,在组件销毁时调用,componentWillUnmount;

    function TimeToLog(){
    	let [time,setTime] = useState(0);
        let timer = null;
        useEffect(()=>{
            timer = setInterval(()=>setTime(Date().toLocaleString()),2000);
            return ()=>clearTimeout(timer);	
        });
    	return(<p>时间:{time}</p>);
    }
    
自定义Hook

封装自定义逻辑状态,已达到状态的复用。

说明:

  • 每次复用都是独立的state,可多次调用。
  • 定义规则以use**开头。
  • 使用场景:表单处理、动画、订阅、计时器。
  • 自定义组件在使用useEffect时指定依赖项(指定第二个参数)
import React,{useState,useEffect} from 'react';

// 定义在线状态
const statusMap = new Map([[0,"grey"],[1,"green"],[2,"yellow"],[3,"red"]]);
function useOnlineStatus(flag){
	const [status,setStatus] = useState(null);

	useEffect(()=>{
		setStatus(statusMap.get(flag));
	},[flag]);
	
	return status;
}

// 在业务组件中使用
function showPersonInfo(props){
	const statusStr = useOnlineStatus(props.status);
	
	return (<div>
		<p style={{color:statusStr}}>{props.name}</p>
	</dvi>);
}
其他Hook说明

来自官网的贴图
在这里插入图片描述

useState
  1. 手动操作对象合并
    setPersonObj(preObj=>{
    	return {...preObj,...newObj};
    });
    
    useReducer适合用于管理包含多个子值得state对象。
  2. 初始值可传入计算函数;该函数在初始时调用一次
    const [name,setName] = useState(()=>nameFormatter(props.name));
    
useEffect
  1. 延时调用执行;需要DOM同步更新的变化时
  2. 接受第二个参数,定义属性值发生变化才会重新渲染
useContext
  1. 接收一个context对象,即<MyContext.Provider>value值,使用props在组件内获取使用。
  2. context发生变化时,组件进行更新渲染;
import React,{useContext} from 'react';
import UserContext from './MyContext';

export default function ChildOne(){
    const MyContext = useContext(UserContext);

    return (<div>
        <p>ChildOne</p>   
        <span>{MyContext.info.name}</span> 
    </div>)
}	
useReducer
  1. useState在某些方面的替代方案;
  2. 类似redux进行共享数据状态管理;

reducer.js 用于几种处理数据;数据逻辑处理。

function reducer(state,action){
    debugger;
    switch(action.type){
        case "add":
            let arr = state.arr;
            arr.push(action.name)
            return {arr:arr}
        case "delete":
            state.arr.splice(action.id,1);
            return {arr:state.arr}
        default:
            throw new Error();
    }
}
export default reducer;

childOne.js 组件用于展示数据列表。并且进行删除操作。

import React from 'react';
export default function ChildOne(props){
    
    let {data,dispatch} = props;
    return (<div>
        {data.arr.map((item,index)=><div>
                <span>{item}</span>
                <span onClick={e=>dispatch({type:"delete",id:index})}>-</span>
            </div>)}
    </div>)
}

childTwo.js用于添加数据操作。

import React,{useState} from 'react';
export default function ChildOne(props){
    const [name,setName] = useState();
    let {dispatch} = props;

    return (<div>
        <input value={name} onChange={e=>setName(e.target.value)} />
        <button onClick={e=>dispatch({type:'add',name:name})}>add</button>
    </div>)
}

index.js 作为父组件,传递给两个子组件的state数据,以及分发事件dispatch

import React,{useReducer} from 'react';

import Reducer from './useReducer';
import ChildOne from "./childOne";
import ChildTwo from './childTwo';

function Index(){
	// hook reducer
    const [obj,dispatch] = useReducer(Reducer,{arr:[]});
    return (<div style={{border:"1px solid #bbb"}}>
            <ChildOne data={obj} dispatch={dispatch} />
            <ChildTwo dispatch={dispatch} />
        </div>);
}

useReducer可配合useContext使用。进行跨组件通信、跨组件数据共享。

useCallback
  1. 返回一个memoized函数,接受一个回调函数及依赖项数组作为参数;
  2. 依赖项数组发生变化时,会调用回调函数;
useMemo
  1. 返回一个memoized函数,接受一个回调函数及依赖项数组作为参数;
useRef
  1. 返回一个可变的ref对象,在整个组件声明周期中保持不变;
useImperativeHandle
  1. 在使用ref时自定义暴露给父组件的实例值
useLayoutEffect
  1. 在重新渲染时同步更新DOM;
useDebugValue
  1. 用于在React开发工具中显示自定义Hook的标签。
使用Hooks的疑问难点
  1. 父组件获取子组件实例的数据(通过调用子组件的方法获取)
    // 父组件
    function ParentInfo(){
    	let childRef = null;
    	function handleGetInfo(e){
            e.stopPropagation();
            let obj = childRef().getInfo();
            console.log(obj);
        }
    	return (<div>
    		<button onClick={handleGetInfo}>获取</button>
        	<ChildInfo onRef={ref=>childRef=ref} />
        </div>);
    }
    // 子组件实例
    function ChildInfo(props){
        let [name,setName] = useState("admin");
        useEffect(()=>{
            let {onRef} = props;
            onRef(()=>{
                return {
                    getInfo:getInfo
                }
            });
        });
        function getInfo(){
            return {
                name:name
            }
        }
        return (<input value={name} onChange={e=>setName(e.target.value)} />);
    }
    
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heroboyluck

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值