React Hooks常用钩子及基本原理解读
一. 简述
在以往的react16.8前, 我们React组件创建方式基本包含两种方式: 类组件, 纯函数组件。
React 团队希望组件最佳写法应该是函数,而不是类。
然而常规的纯函数组件有以下特点:
- 没有状态
- 没有生命周期
- 没有 this
因存在如上特点,使得纯函数组件只能做UI展示的功能, 涉及到状态的管理与切换就不得不用到类组件或这redux。
但因为简单的页面也是用类组件,同时要继承一个React实例,使得代码会显得很重。
‘Hooks’ 单词意思为:钩子。
React Hooks 意思是:组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码“钩”进来。
React Hooks常用钩子有如下四种:
- useState()
- useContext()
- useReducer()
- useEffect()
使用hooks 我们会发现没有了继承,渲染逻辑,生命周期等, 代码看起来更加的轻便简洁了。
React 约定,钩子一律使用 use 前缀命名 (自定义钩子都命名为:useXXXX)
二. 常用举例及原理分析
useState 状态钩子
官方示例:
import React, {useState} from 'react' const AddCount = () => { const [ count, setCount ] = useState(0) const addcount = () => { let newCount = count setCount(newCount+=1) } return ( <> <p>{count}</p> <button onClick={addcount}>count++</button> </> ) }
原理:
// 我们实现一个简易版的useState let memoizedStates = [ ] // 多个useState 时需要使用数组来存 let index = 0 function useState (initialState) { memoizedStates[index] = memoizedStates[index] || initialState let currentIndex = index; function setState (newState) { memoizedStates[currentIndex] = newState render() } return [memoizedStates[index++], setState] }
useContext 共享状态钩子
该钩子的作用是,在组件之间共享状态。
可以解决react逐层通过Porps传递数据。
import React,{ useContext } from 'react' const ShareContext= () => { const AppContext = React.createContext({}) const A =() => { const { name } = useContext(AppContext) return ( <p>我是A组件的名字{name}<span>我是A的子组件{name}</span></p> ) } const B =() => { const { name } = useContext(AppContext) return ( <p>我是B组件的名字{name}</p> ) } return ( <AppContext.Provider value={{name: 'hook测试'}}> <A/> <B/> </AppContext.Provider> ) } export default ShareContext
useContext(context) 是针对 context (上下文) 提出的api。
它接受React.createContext()的返回结果作为参数(也就是context对象并返回最近的context)。
使用useContext将不再需要Provider 和 Consumer。
当最近的context更新时,那么使用该context的hook将会重新渲染。
useReducer(): Action 钩子
React本身不提供状态管理。
而useReducer() 提供了状态管理。
其基本原理是通过用户在页面中发起action, 从而通过reducer方法来改变state, 从而实现页面和状态的通信。
import React,{useReducer} from 'react' const MyReducer= () => { const reducer = (state, action) => { if(action.type === ''add){ return { ...state, count: state.count +1, } }else { return state } } const addcount = () => { dispatch({ type: 'add' }) } const [state, dispatch] = useReducer(reducer, {count: 0}) return ( <> <p>{state.count}</p> <button onClick={addcount}>count++</button> </> ) } export default MyReducer
使用useReducer() 代替了Redux的功能, 但useReducer 无法提供中间件等功能。
useEffect(): 副作用钩子
React常规开发中,我们习惯将一些处理副作用的操作,如:异步请求等 放在特定的生命周期中。
useEffect 则是为函数组件提供了副作用的钩子。
useEffect() : 接收两个参数, 第一个是进行的异步操作, 第二个是数组,用来给出Effect的依赖项。
第二个参数(数组)发生变化, ==useEffect()==就会执行。
第二项不填时, useEffect() 会在每次组件渲染时执行。
import React, { useState, useEffect } from 'react' const AsyncPage = ({name}) => { const [loading, setLoading] = useState(true) const [person, setPerson] = useState({}) // useEffect 类似compomnetDidMount 初始化会执行,更新时会执行 useEffect(() => { setLoading(true) setTimeout(()=> { setLoading(false) setPerson({name}) },3000) },[name]) return ( <div> {loading?<p>Loading...</p>:<p>{person.name}</p>} <div/> ) } const PersonPage = () =>{ const [state, setState] = useState('') const changeName = (name) => { setState(name) } return ( <> <AsyncPage name={state}/> <button onClick={() => {changeName('名字1')}}>名字1</button> <button onClick={() => {changeName('名字2')}}>名字2</button> </> ) } export default PersonPage
创建自己的Hooks
有时候我们需要创建自己想要的Hooks, 来满足更便捷的开发。
import React, { useState, useEffect } from 'react' const usePerson = (name) => { const [loading, setLoading] = useState(true) const [person, setPerson] = useState({}) useEffect(() => { setLoading(true) setTimeout(()=> { setLoading(false) setPerson({name}) },2000) },[name]) return [loading,person] } const AsyncPage = ({name}) => { const [loading, person] = usePerson(name) return ( <div> {loading?<p>Loading...</p>:<p>{person.name}</p>} </div> ) } const PersonPage = () =>{ const [state, setState]=useState('') const changeName = (name) => { setState(name) } return ( <div> <AsyncPage name={state} /> <button onClick={() => {changeName('名字1')}}>名字1</button> <button onClick={() => {changeName('名字2')}}>名字2</button> </div> ) } export default PersonPage
上面自定义了一个Hooks, 它接受一个字符串, 返回一个数组, 数组中的两个状态在使用usePerson() 时, 会根据传入的不同反而返回不同的状态。
React Hooks 概要及未来
根据官方文档的说法:
完全可选
- 100%向后兼容 (Hook 不会含任何破坏性改动)
- 现在可用 (Hook 已发布于 v16.8.0)
- 没有计划从React中移除class
- Hook不会影响对React概念的理解 (Hook 为React提供了相关API:props, state,context, refs以及生命周期)
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
React 组件中的state和setState()你知道多少
这篇文章主要为大家详细介绍了React组件中的state和setState(),文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助2022-03-03React UI组件库之快速实现antd的按需引入和自定义主题
react入门学习告一段路,下面这篇文章主要给大家介绍了关于React UI组件库之快速实现antd的按需引入和自定义主题的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下2022-07-07React Hooks - useContetx和useReducer的使用实例详解
这篇文章主要介绍了React Hooks - useContetx和useReducer的基本使用,本文通过实例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2022-11-11
最新评论