react-hook
简介:Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
react-hook分为下面几点
- useState
- memo
- useMemo
- useCallback
- useReducer
- useContext
- useRef
- useEffect
一、useState
如图:
import React from 'react';
import ReactDOM from 'react-dom';
// useState的原理
// 封装一个useState
let lastState;//定义一个初始值
function useState(initialState/** 传进来的初始值*/){
lastState=lastState||initialState; //如果之前的初始值有值就用之前的,没有就用传进来的
function setState(newState){ //定义设置修改值的方法,把值传给定义的初始值
lastState=newState
render()//重新渲染页面
}
return [lastState,setState]//每次调用之后都会调用来修改里面的值 最后会返回一个数组
}
function App(){
let [number,setNumber]=useState(0)
//useState的定义 ,左边是通过我们的结构赋值的一个函数,第一个是我们定义的变量名,第二个是改变数据的方法,右边是我们引用的useState括号的里面的值就是我们默认定义的初始值
return (
<>
<div>{number}</div>
<button onClick={()=>setNumber(number+1)}>增加</button>
</>
)
}
function render(){
ReactDOM.render(
<App />
,
document.getElementById('root')
);
}
render()
二、memo、useMemo和useCallback
介绍:主要作用用于缓存和监听下数据,数据改变就改变,没有发生改变的就不让他重渲染了
import React,{memo} from 'react';
import ReactDOM from 'react-dom';
function Child({data,addClick}){
// console.log(data,addClick)
console.log("child render")
// 调用传递过来的方法和值
return <button onClick={addClick}>{data.number}</button>
}
Child=memo(Child)//这个一步不写就没有监听了下面就会报错
/**
* 把函数组件传给memo方法,返回一个新的组件,
改造后每次渲染前都会判断一个属性变了没有,
如果属性不变就不渲染,变了才渲染
*/
function App(){
let [number,setNumber]=useState(0);
let [name,SetName]=useState("小明");
let addClick=useCallback(()=>setNumber(number+1),[number]);//返回的是一个函数使用useCallback 两个参数 一个是函数,一个是要改变的值
let data=useMemo(()=>({number}),[number])//返回的是一个对象,一个是返回的值和一个是改变的值
return (
<>
<input value={name} onChange={event=>SetName(event.target.value)}/>
{/* 组件,需要传递的值 */}
<Child data={data} addClick={addClick}/>
</>
)
}
function render(){
ReactDOM.render(
<App />
,
document.getElementById('root')
);
}
render()
三、useReducer
作用:在 hooks 中提供了的 useReducer 功能,可以增强 ReducerDemo 函数提供类似 Redux 的功能,引入 useReducer 后,useReducer 接受一个 reducer 函数作为参数,reducer 接受两个参数一个是 state 另一个是 action 。然后返回一个状态 count 和 dispath,count 是返回状态中的值,而 dispatch 是一个可以发布事件来更新 state 的。
代码:
import React,{memo} from 'react';
import ReactDOM from 'react-dom';
function reducer(state,action){
if(action.type==='add'){
return state+1
}else{
return state
}
}
// 封装useReducer
let lastState; //初始值
function useReducer(reducer,initialState){ //传入方法和传进来的值
lastState=lastState||initialState; //初始值如果有值就用初始化的值,没有就使用传进来的值
function dispatch(action){ //触发方法传进来的是和redux里面一样
lastState=reducer(lastState,action);//把处理的数据结果返回
render()//重新渲染下页面
}
return [lastState,dispatch] //把方法返回出去
}
function Counter(){
let [state,dispatch]=useReducer(reducer,0);
return (
<div>
<p>{state}</p>
<button onClick={()=>dispatch({type:'add'})}>+</button>
</div>
)
}
function render(){
ReactDOM.render(
<Counter />
,
document.getElementById('root')
);
}
render()
五、useContext
作用:如果需要在组件之间共享状态,可以使用useContext()。
import React,{memo,useContext,useState} from 'react';
import ReactDOM from 'react-dom';
// useContext的使用
let AppContext=React.createContext(); //第一步在它们的父组件上使用React的Context API,在组件外部建立一个Context。
function Counter(){
let {state,setState}=useContext(AppContext)//可以直接使用外层AppContext.Provider传递的value的值和方法
return (
<div>
<p>{state.number}</p>
<button onClick={()=>setState({number:state.number+1})}>+</button>
</div>
)
}
function App(){
let [state,setState]=useState({number:0});
return (
<AppContext.Provider value={{state,setState}}>
{/**我们直接用我们生成的context对象里面的provider来包裹自己的组件,组件不管多深就可以可以拿到父组件传递过去的*/}
<div>
<div>
<Counter/>
</div>
</div>
</AppContext.Provider>
)
}
function render(){
ReactDOM.render(
<App />
,
document.getElementById('root')
);
}
render()
六、useEffect和useLayoutEffect
作用:就是hook里面的生命周期,你可以看做是类组件中的 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。
import React,{memo,useContext,useState,useEffect,useLayoutEffect} from 'react';
import ReactDOM from 'react-dom';
function App(){
let [state,setState]=useState(0);
useEffect(()=>{//游览器执行完成之后执行
console.log("useEffect")
console.log(state,"数据")
},[])
useLayoutEffect(()=>{ //游览器执行之前执行 防阻塞模式
console.log("useLayoutEffect")
},[])//传入的是空数组的话就只运行一次,如果是有监听数据的话,当他发生改变的时候会一直执行
console.log("render")
return (
<>
<div>{state}</div>
<button onClick={()=>setState(state+1)}>增加</button>
</>
)
}
function render(){
ReactDOM.render(
<App />
,
document.getElementById('root')
);
}
render()
七、useRef
作用主要是获取dom节点,需要绑定在节点上面
import React,{useRef} from 'react';
import ReactDOM from 'react-dom';
function App(){
let ref=useRef()
console.log(ref,"demo")
return (
<>
<button ref={ref}>增加</button>
</>
)
}
function render(){
ReactDOM.render(
<App />
,
document.getElementById('root')
);
}
render()