React hooks 快速尝鲜
技.技术研究125 阅读约 10 分钟
React hooks 快速尝鲜
useState
const [num, setNum] = useState("0");
// useState 函数帮我们解构了一个变量 num 和 setNum 函数,并且将变量初始值赋值为 0
// useState除了可以静态的赋值还可以useState(()=>init)
// useState返回的更新数据方法setXXX(currentState=>currentState+1)默认会传入当前的数据状态
useReducer
// 创建一个 reducer
function myReducer(state, action){
switch(action.type) {
case "add": return state + 1
case "minus": return state - 1
default: state
}
}
const [state, dispatchNum] = useReducer(myReducer, 0)
dispatchNum({ type: add })
useEffect
// Effect Hook 可以让你在函数组件中执行副作用操作
// 解释这个 Hook 之前先理解下什么是副作用。网络请求、订阅某个模块或者 DOM 操作都是副作用的例子,Effect Hook是专门用来处理副作用的。正常情况下,在Function Component的函数体中,是不建议写副作用代码的,否则容易出 bug。
// useEffect 可以看做是替代了一些生命周期
const [num, setNum] = useState(0)
useEffect(() => {
const interval = setInterval(() => {
setNum(num + 1)
}, 1000)
// 最后要 return 一下,记得清楚定时器
return () => clearInterval()
}, [num])
// useEffect 会在组件第一次渲染时执行
// useEffect 第一个参数函数相当于生命周期中的 componentDidMount,
// useEffect 第二个参数为依赖项,当依赖项改变时才会执行 useEffect 一个参数函数,不传的话 useEffect 会在每次 DOM 渲染后执行
// useEffect 第一个参数函数返回值(return)相当于生命周期中的 componentWillUnMount
// 当useEffect 第一个参数的返回值是一个函数的时候,React 会在下一次执行这个副作用之前执行一遍清理工作,整个组件的生命周期流程可以这么理解:组件挂载 --> 执行副作用 --> 组件更新 --> 执行清理函数 --> 执行副作用 --> 组件更新 --> 执行清理函数 --> 组件卸载
// 第二个参数是一个数组,可以传多个值,一般会将 Effect 用到的所有 props 和 state 都传进去。
// 当副作用只需要在组件挂载的时候和卸载的时候执行,第二个参数可以传一个空数组[],实现的效果有点类似componentDidMount和componentWillUnmount的组合
useContext
// 新建一个context文件myContext.js
import React from 'react'
export default React.createContext("")
// 在另一个文件中引入
import MyContext from './myContext'
// 通过MyContext.Provider 传值
<MyContext.Provider value="test">
<Component/>
</MyContext.Provider>
// 当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定
// 在组件中使用
import {useContext} from 'react'
import MyContext from './myContext'
function test() {
const contextValue = useContext(MyContext)
return <div>{contextValue}</div>
}
useRef
import {useRef} from 'react'
function testRef() {
const inputRef = useRef()
useEffect(() => {
console.log(inputRef)
})
return <input ref={inputRef}>测试ref</input>
}
useMemo
某些情况下组件中的值需要依赖state进行计算后得到,由于每次组件更新都会去重新计算,为了减少性能消耗,可以使用useMemo缓存值,仅仅当依赖改变时,才重新计算。
- 参数:计算函数,依赖数组
则函数仅会在某个依赖项改变时才重新计算memoized 值。
const [count, setCount] = useState(0);
//expensive 需要依赖count计算得到
const expensive = useMemo(() => {
let sum = 0;
for (let i = 0; i < count; i++) {
sum += i;
}
return sum;
//只有count变化,这⾥才重新执⾏
}, [count]);
useCallback
由于每次组件更新都会内部函数都会重新创建一次,为了节省性能,可以使用useCallback,使内联回调函数仅仅在传入依赖项改变时进行更新。
- 参数:内联回调函数,依赖数组
则函数仅会在某个依赖项改变时才进行更新。
const [count, setCount] = useState(0);
const addClick = useCallback(() => {
setCount(count+1)
}, [count]);
useImperativeHandle
- 有些情况下我们需要父组件把ref传递给子组件,仅仅使用 forwardRef 将子组件的ref属性都暴露给父组件是危险的,也违反了封装原则,useImperativeHandle允许在子组件中把自定义实例附加到父组件传过来的ref上,减少暴露给父组件的属性
- 参数: 3个,ref, createHandle处理函数,其返回值会替换父组件传来的ref.current, [state]依赖项
useImperativeHandle(ref, createHandle, [state])
- 例子
let Child = (props, ref) =>{
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus()
}
}));
return <input ref={inputRef} />;
}
Child = forwardRef(Child );
const Father=() => {
const ref = useRef(null);
return (
<>
<Child ref={ref}/>
<button onClick={()=>{ ref.current.focus()}}>聚焦</button >
</>
)
}
useLayoutEffect
- 作用 :与useEffect相同,都是用来执行副作用。
- 特点 :useEffect是在渲染之后调用effect,也就是下一桢执行,是异步的;
而useLayoutEffect在当前帧Render tree计算布局(Layout)信息后,渲染前,同步调用effect。官方文档建议使用标准useEffec。
自定义Hook
- 定义:函数以use开头并且在函数内部调用其他hooks,并且返回一个数组,可以实现逻辑复用。
- 例子 :
//实现一个thunk
const useThunk =(reducer,initalState)=>{
const [state,dispatch] =useReducer(reducer,initalState)
const thunkDispatch = (action)=>{
if( action instanceof Function){ //如果action是函数,传入新的dispatch执行action
return action (thunkDispatch,()=>state)
}else{
dispatch(action )
}
return [state,thunkDispatch]
}
相关文章
评论 (0)
还没有评论,来抢沙发
