使用Hooks理由
1.高阶组件为啦复用,导致代码层级复杂
2.生命周期的复杂
3.写成function组件,无状态组件,因为需要状态,又改成class,成本高
useState(保存组件状态)
import React, { useState } from 'react'
export default function App() {
// useState("kerwin") 返回一个数组 数组第一个参数是你传递的参数 第二个参数是一个方法
const [name, setName] = useState("kerwin")
const [age, setage] = useState(100)
// console.log(obj)
return (
<div>
<button onClick={() => {
// console.log(name)
setName("xiaoming")//每次执行都会使App函数重新执行
setage(18)//每次执行都会使App函数重新执行
}}>click</button>
app-{name}-{age}
</div>
)
}
useEffect(处理副作用)和useLayoutEffect (同步执行副作用)
useEffect(()=>{
//effect
return ()=>{
//组件销毁时调用
}
},[依赖的状态;空数组,表示不依赖])
//如果是空数组表示不依赖,也就可以认为useEffect只会执行一遍
//不要对Dependencies撒谎,如果你明明使用啦某个变量,却没有申明在依赖中,你等于向React撒啦谎,后果就是,当依赖的变量改变时,useEffect也不会再次执行,eslint会报警告
//注意点:1.useEffect可以在一个文件中使用多次
import React,{useState,useEffect} from 'react'
export default function App() {
const [name, setname] = useState("kerwin")
useEffect(() => {
setname(name.substring(0,1).toUpperCase()+name.substring(1))
}, [name])
// 第一次执行一次, 之后name(依赖)更新也会执行
return (
<div>
app-{name}
<button onClick={()=>{
setname("xiaoming")
}}>click</button>
</div>
)
}
useEffect和useLayoutEffect有什么区别?
简单来说就是调用时机不同, useLayoutEffect 和原来 componentDidMount & componentDidUpdate 一致,在react完成DOM更新后马上同步调用的代码,会阻塞页面渲染。而 useEffect 是会在整个页面渲染完才会调用的代码。(dom树和渲染树)
官方建议优先使用 useEffect
However, we recommend starting with useEffect first and only trying useLayoutEffect if that causesa problem
实际使用时如果想避免页面抖动(在 useEffect 里修改DOM很有可能出现)的话,可以把需要操作DOM的代码放在 useLayoutEffect 里。在这里做点dom操作,这些dom修改会和 react 做出的更改一起被一次性渲染到屏幕上,只有一次回流、重绘的代价。
总结:如果需要操作dom节点,那么代码就应该放在useLayoutEffect里面,反之就使用useEffect
useCallback(记忆函数)
防止因为组件重新渲染,导致方法被重新创建 ,起到缓存作用; 只有第二个参数 变化了,才重新声明一次
var handleClick = useCallback(()=>{
console.log(name)
},[name])
<button onClick={()=>handleClick()}>hello</button>
//只有name改变后, 这个函数才会重新声明一次,
//如果传入空数组, 那么就是第一次创建后就被缓存, 如果name后期改变了,拿到的还是老的name。
//如果不传第二个参数,每次都会重新声明一次,拿到的就是最新的name.
useMemo 记忆组件
useCallback 的功能完全可以由 useMemo 所取代,如果你想通过使用 useMemo 返回一个记忆函数也是完全可以的。
useCallback(fn, inputs) is equivalent to useMemo(() => fn, inputs).
唯一的区别是:useCallback 不会执行第一个参数函数,而是将它返回给你,而 useMemo 会执行第一个函数并
且将函数执行结果返回给你。所以在前面的例子中,可以返回 handleClick 来达到存储函数的目的。
所以 useCallback 常用记忆事件函数,生成记忆后的事件函数并传递给子组件使用。而 useMemo 更适合经过函数计算得到一个确定的值,比如记忆组件
useRef(保存引用值)
const myswiper = useRef(null);
<Swiper ref={myswiper}/>
useReducer和useContext(减少组件层级)
import React from 'react'
var GlobalContext= React.createContext()
// 注意此时的reduecer 返回值是一个对象 {isShow:false,list:[]}
function App(props){
let [state,dispatch] = useReducer(reducer,{isShow:true,list:[]})
return <GlobalContext.Provider value={{
dispatch
}}>
<div>
{
state.isShow?
<div >我是选项卡</div>
:null
}
{props.children}
</div>
</GlobalContext.Provider>
}
function Detail(){
var {dispatch} = useContext(GlobalContext)
useEffect(() => {
//隐藏
dispatch({
type:"Hide",
payload:false
})
return () => {
//显示
dispatch({
type:"Show",
payload:true
})
};
}, [])
return <div>
detail
</div>
自定义hooks
当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。
必须以“use”开头吗?必须如此。这个约定非常重要。不遵循的话,由于无法判断某个函数是否包含对其内部 Hook
的调用,React 将无法自动检查你的 Hook 是否违反了 Hook 的规则