持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
使用hooks理由
- 高阶组件为了复用,导致代码层级复杂
- 生命周期的复杂
- 写成functional组件,无状态组件,因为需要状态,又改成class成本高
1.useState(保存组件状态)
const [state,setstate]=useState(initialState)
useState将会返回两个参数,一个是设置的状态,一个是改变这个状态的方法,我们可以使用结构方式获取。 (1).我们可以打印查看useState返回的参数
import React, { useState } from 'react'
export default function Hookscomp(){
const data = useState([])
console.log(data)
return (
<div>hooks</div>
)
}
(2).使用方式
import React, { useState } from 'react'
export default function Hookscomp(){
const [number,setNumber]=useState(1)
return (
<>
<div>{number}</div>
<button onClick={()=>{setNumber(2)}}>改变Number</button>
</>
)
}
2.useEffect(处理副作用)和useLayoutEffect(同步执行副作用)
useEffect 在Dom节点及页面渲染完成后执行,其中依赖处如果为空数组则执行一次,如果设置为某个状态,当这个状态发生改变时,useEffct内副作用将会执行,同一个函数式组将中可以有多个useEffect,return在函数销毁时执行,可用于清除定时器等
useEffect(()=>{
// effect
return ()=>{
//cleanup
}
},[依赖状态,空数组标识不依赖])
注意:虽然函数式组件中并没有生命周期,但useEffect可以解决一些生命生命周期该做的事情,可以将请求放在useEffect中,并使用空依赖执行一次。
useEffct与和useLayoutEffect
区别 简单来说就是调用时机不同,useLayoutEffect和原来componentDidMount & componentDidUpdate一致,在react完成Dom更新后马上同步调用代码,会阻塞页面渲染,而useEffect是会在整个页面渲染完成后才会调用 官方建议使用useEffct 在实际使用过程中如果想避免页面抖动,(在useEffct里修改Dom很有可能会出现),可以把需要操作Dom的代码放在useLayoutEffect中在这里做Dom操作,这些Dom修改会和React做出的更改一起被一次性渲染到屏幕上,只有一次回流、重绘的代价。
3.useCallback(记忆函数)
由于每次状态改变,函数组件将会重新执行,方法将会重新创建,该函数防止因为组件重新渲染,导致方法被重新创建,起到缓存作用,只有第二个参数变化了,才重新声明一次。
var handleClick=useCallback(()=>{
console.log(name)
},[name])
1.只有name改变后,这个函数才会重新声明一次
2.如果传入空数组,那么就是第一次创建后被缓存,如果name后期改变了,那么得到的还是老的name。
3.如果不传入第二个参数,每次都会重新声明一次,拿到的就是最新的name
4.useMemo(记忆组件-可以当做vue中computed使用)
useCallback的功能完全可以由useMemo所取代,如果你想通过使用useMemo返回一个记忆函数也是完全可以的 唯一的区别:useCallback不会执行第一个参数函数,而是将它返回,而useMemo会执行第一个函数并返回函数执行结果, useCallback适用记忆函数,生成记忆后的函数并传递给子组件使用,而useMemo更适合经过函数计算得到一个确定的值,比如记忆组件
5.useRef(保存引用值)
const myRefs=useRef(null)
<Component ref={myRefs}/>
6.useReducer和useContext(减少组件层级)
父组件引入GlobalContext,并使用GlobalContext.Provider(生产者)
import React from 'react';
import Bus from './day2/bus'
export const GlobalContext=React.createContext()
class Swipers extends Component {
render(){
return(
<GlobalContext.Provider value={
{
name:'全局context测试',
}
}>
<Bus />
</GlobalContext.Provider>
)
}
}
但获取方式与类组件方式发生了变化,不再使用GlobalContext.Consumer消费者获取而是使用useContext函数获取
function Demo(){
const value=useContext(GlobalContext) // 定义好的全局状态
console.log(value) // value即可获取全局状态
}
useReducer用法如果有Redux学习经验可以理解为简略版Redux,reducer执行操作,initialState初始值,在reducer函数中根据reducer的type对数据进行操作,而type是由dispatch推入,获取数据则使用state获取。
import React, { useReducer } from 'react'
const reducer=(preState,action)=>{
const data={...preState}
switch (action.type){
case 'add':
data.number++
return data;
case 'increase':
data.number--
return data;
default:
return preState;
}
}
const initialState={
number:0
}
export default function Hookscomp(){
const [state,dispatch]=useReducer(reducer,initialState)
return (
<>
<button onClick={()=>{dispatch({type:'increase'})}}>-</button>
<div>{state.number}</div>
<button onClick={()=>{dispatch({type:'add'})}}>+</button>
</>
)
}
useReducer和useContext联用可以模拟Redux 通过useContext对state及dispatch进行提升,使得子组件可以共享状态及dispatch进行状态修改
import React, { useContext, useReducer } from 'react'
const GlobalContext=React.createContext()
const reducer=(preState,action)=>{
const data={...preState}
switch (action.type){
case 'add':
data.number++
return data;
case 'increase':
data.number--
return data;
default:
return preState;
}
}
const initialState={
number:0
}
export default function Hookscomp(){
const [state,dispatch]=useReducer(reducer,initialState)
return (
<GlobalContext.Provider value={{state,dispatch}}>
<Child1 />
<Child2 />
</GlobalContext.Provider>
)
}
function Child1(){
const {state,dispatch}=useContext(GlobalContext)
return (
<>
<button onClick={()=>{dispatch({type:'increase'})}}>-</button>
<div>{state.number}</div>
</>
)
}
function Child2(){
const {state,dispatch}=useContext(GlobalContext)
return (
<>
<div>{state.number}</div>
<button onClick={()=>{dispatch({type:'add'})}}>+</button>
</>
)
}
7.自定义hooks
必须以
use
开头,如果不遵循,无法判断某个函数是否包含对内部Hooks的调用,React将无法自动检查你的Hook是否违反了Hook的规则。 示例:
function useFilter(){
const [name,setName]=useState() // 定义hooks中可以使用React Hook
return {
name
}
}
function HookUse(){
const {name}=useFilter()
}