react Hook

Hook是React16.8的新增特性、它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。引入hook有什么意义呢?

1、丰富了函数组件的能力、使其具有状态管理能力;
2、组件逻辑复用,Hook表现的更好【写共用方法一样】,而比class组件的 mixin【废弃了】、HOC、render props更加易懂;
3、class复杂组件正在变的费解、不易拆解、测试,逻辑混乱;

在react中已经内置了一些hook 【useStateuseEffect、useMemo、useCallback、useRef、useContext、useReducer】和 可自定义hook。下面一个个分析其用处。

一、useState---函数添加状态、使其实现state 和 setState功能 【重要】

ps:默认函数组件没有state, 且是一个纯函数,执行完即销毁, 无法存储state,需要state Hook, 把state功能 "钩"到纯函数中。

用法:

1、接受一个参数作为初始值
2、返回一个数组、第一个值为状态、第二个值为改变状态的函数

// 数组结构 推荐[name  setName]格式; 可见 useState 返回的是一个数组
function StateHookDemo () => {
    const [name, setName] = useState('terry')
    return <div onClick={() => setName('jerry')}>点击更新</div>
}
export default StateHookDemo

二、useEffect---模拟class组件的生命周期,添加结束渲染的信号【重要】

用法:

1、接受一个函数作为参数
2、接收第二个参数数组[],依赖列表, 只有依赖更新时,才会执行函数, 也可以不传;

function effectHookDemo () => {
    const [name, setName] = useState('terry')
    //  模拟componentDidMount 和 componentDidUpdate
   //  即在初始化会打印 entry ,当点击更新是 也会打印entry
    useEffect(() => {
          console.log(‘entry’)  //  初始化会打印 , 点击更新也会打印
    });
  
  //  模拟 componentDidMount
    useEffect(() => {
          console.log(‘entry’)  //  初始化会打印 , 点击更新不会打印
    }, []);  //第二个参数是空数组
  
    //  模拟 componentDidUpdata
    useEffect(() => {
          console.log(‘entry’)  //  初始化不会打印 , 点击更新会打印
    }, [name]);  //第二个参数是依赖, 即当name更新了才触发
  
    // 模拟componentWillUnMount
     useEffect(() => {
          const timer = setIntervel(() => {
              console.log(Date.now())
          }, 1000)
       // 返回一个函数
      //  模拟componentWillUnMount
         return () => {
                clearInterval(timer )
          }
    }, []);  

    return <div onClick={() => setName('jerry')}>点击更新</div>
}
export default effectHookDemo

三、useRef---长久保存数据【可用来获取dom】

作用:

1、保存一个值, 在整个生命周期中维持不变
2、重新赋值ref.current不会触发重新渲染

function refHookDemo () => {
   const btnRef = useRef(null)
   useEffect(() => {
     console.log(btnRef.current) // DOM节点
   }, [])
    return <div>
      <button ref={btnRef}>click</button>
    </div>
}
export default refHookDemo

四、useContext---带着组件去流浪

用法:

1、需要引入useContext和 createContext
2、通过createContext创建一个context句柄
3、Context.Provider来确定数据共享的范围
4、通过value来分发内容
5、在子组件在中通过useContext(context句柄)来获取数据

// 1、引入useContext和 createContext
import React, { useContext, createContext } from 'react'
// 颜色主题
const themes = {
  light: {
      background: '#eee'
  },
  dark: {
      background: '#222'
  }
}
// 2、通过createContext创建一个context句柄
const ThemeContext = createContext(themes.light) // 初始值
function ThemeButton() {
//5、 在子组件在中通过useContext(context句柄)来获取数据
    const theme = useContext(ThemeContext)
    return <button style={{ background: theme.background}}>
        hello world
    </button>
}
function Toolbar() {
    return <div>
        <ThemeButton></ThemeButton>
    </div>
}
function App() {
    // 3、Context.Provider来确定数据共享的范围
    // 4、通过value来分发内容
    return <ThemeContext.Provider value={themes.dark}>
        <Toolbar></Toolbar>
    </ThemeContext.Provider>
}
export default App

五、useReducer---借鉴redux, 应对复杂的state变化

用法:

1、 数据仓库 store
2、需要管理者 reducer
3、useReducer(reducer, store) 返回一个数组,[state, dispatch]

import React, { useReducer } from 'react'
const store = { count: 0 } // 创建仓库store
//2、需要管理者 reducer
const reducer = (state, action) => {
    switch (action.type) {
        case 'increment':
            return { count: state.count + 1 }
        case 'decrement':
            return { count: state.count - 1 }
        default:
            return state
    }
}
function App() {
    // 很像 const [count, setCount] = useState(0)
    const [state, dispatch] = useReducer(reducer, store)
    return <div>
        count: {state.count}
        <button onClick={() => dispatch({ type: 'increment' })}>increment</button>
        <button onClick={() => dispatch({ type: 'decrement' })}>decrement</button>
    </div>
}
export default App

ps: useReducer 和 redux的区别
1、useReducer是useState的代替方案, 用于state的复杂变化
2、useReducer 是单个组件状态管理,组件通信还是要props
3、redux是全局的状态管理, 多组件共享数据

六、useMemo---缓存hook 缓存数据 用于性能优化

用法:

1、 接收一个函数作为参数
2、第二个参数为依赖列表
3、返回一个

import React, { useState, memo, useMemo } from 'react'
// 类似 class PureComponent ,对 props 进行浅层比较
const Child = memo(({ userInfo }) => {
    console.log('Child render...', userInfo) // 不用useMemo的话, 点击click 这个会打印 重新渲染
    return <div>
        <p>This is Child {userInfo.name} {userInfo.age}</p>
    </div>
})
// 父组件
function App() {
    console.log('Parent render...') 
    const [count, setCount] = useState(0)
    const [name, setName] = useState('双越老师')
    // const userInfo = { name, age: 20 }
    // 用 useMemo 缓存数据,有依赖
    const userInfo = useMemo(() => {
        return { name, age: 21 }
    }, [name])
    return <div>
        <p>
            count is {count}
            <button onClick={() => setCount(count + 1)}>click</button>
        </p>
        <Child userInfo={userInfo}></Child>
    </div>
}
export default App

七、useCallback---缓存hook 缓存函数 用于性能优化

用法:

1、 接收一个函数作为参数
2、第二个参数为依赖列表
3、返回一个函数

import React, { useState, memo, useMemo, useCallback } from 'react'
// 子组件,memo 相当于 PureComponent
const Child = memo(({ userInfo, onChange }) => {
    console.log('Child render...', userInfo) // 看是否会打印
    return <div>
        <p>This is Child {userInfo.name} {userInfo.age}</p>
        <input onChange={onChange}></input>
    </div>
})
// 父组件
function App() {
    console.log('Parent render...')
    const [count, setCount] = useState(0)
    const [name, setName] = useState('terry')
    // 用 useMemo 缓存数据
    const userInfo = useMemo(() => {
        return { name, age: 21 }
    }, [name])
    // function onChange(e) {
    //     console.log(e.target.value)
    // }
    // 用 useCallback 缓存函数
    const onChange = useCallback(e => {
        console.log(e.target.value)
    }, [])
    return <div>
        <p>
            count is {count}
            <button onClick={() => setCount(count + 1)}>click</button>
        </p>
        <Child userInfo={userInfo} onChange={onChange}></Child>
    </div>
}
export default App
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,809评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,189评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,290评论 0 359
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,399评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,425评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,116评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,710评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,629评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,155评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,261评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,399评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,068评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,758评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,252评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,381评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,747评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,402评论 2 358

推荐阅读更多精彩内容

  • 主要介绍 useState useEffect useReducer useContext 用法 你还在为...
    叫我苏轼好吗阅读 27,419评论 3 41
  • 现在编写新的组件的时候我们有两个选择:class组件和函数组件。那么什么是函数组件呢? 现在来看一段函数: 可以看...
    arial_1df2阅读 354评论 0 0
  • 一、react hook介绍 Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情...
    dream_Q阅读 996评论 0 2
  • 关于React Hook React Hook 对于React来说无疑是一个伟大的特性,它将React从类组件推向...
    Mstian阅读 2,378评论 0 11
  • 什么是React Hook? 一个特殊的函数,用于钩入React的特性。它鼓励我们将通用逻辑封装成Hook而不是工...
    南山码僧阅读 623评论 0 7