React Hooks 一步到位
useState
用来声明状态变量。
import React, { useState } from 'react';
// ...
const [ count , setCount ] = useState(0);
// ...
- count 声明的变量
- setCount 设用来更新变量的函数
- 0 初始值
- 多个状态声明不能出现在条件判断语句中
useEffect
用来代替生命周期函数。
import React, { useEffect } from 'react';
useEffect(()=>{
    // some code
})
- 第一次组件渲染和每次组件更新都会执行这个函数
- useEffect中的函数的执行不会阻碍浏览器更新视图,这些函数是异步的
使用 useEffect 实现类似 componentWillUnmount
useEffect(()=>{
    return () => {
        // some code
    }
})
- 返回一个函数实现解绑
- 但是这样会导致每次状态发生变化,useEffect 都进行解绑
useEffect(()=>{
    return () => {
        // some code
    }
}, [])
使用第二个参数,制定哪些状态发生变化时再解绑
useContext
跨越组件层级直接传递变量,实现状态共享。
- useContext 解决的是组件之间值传递的问题
- redux 解决的是应用中统一管理状态的问题
- useContext 通过和 useReducer 的配合使用,可以实现类似 Redux 的作用
Outer 组件
import React, { createContext } from 'react'
const ValueContext = createContext()
function Outer(){
    return (
        <>
            <ValueContext.Provider value={'我是传向 Inner 组件的值'}>
                <Inner />
            </ValueContext.Provider>
        </>
    )
}
export default Outer;
- 使用 createContext 创建 context
- 使用 createContext 同时生成组件
- 闭合标签将组件包裹
Inner 组件
import React, { useContext  } from 'react'
const value = useContext(CountContext)
function Inner(){
    return (
        <>
            <p>{value}</p>
        </>
    )
}
export default Inner;
使用 useContext 来使用上下文
useReducer
用来实现类似 redux 功能
import React, { useReducer } from 'react';
function Demo(){
    const [ count, dispatch ] = useReducer((state,action)=>{
        switch(action){
            case 'add':
                return state+1
            case 'sub':
                return state-1
            default:
                return state
        }
    },0)
    return (
       <>
           <h2>分数:{count}</h2>
           <button onClick={()=>dispatch('add')}>加</button>
           <button onClick={()=>dispatch('sub')}>减</button>
       </>
    )
}
export default Demo
- state 第一个参数 状态
- action 控制业务逻辑的判断参数
模拟 Redux
- useContext:可访问全局状态,避免一层层的传递状态
- useReducer:通过action的传递,更新复杂逻辑的状态
颜色共享组件 color.js
import React, { createContext,useReducer } from 'react';
export const ColorContext = createContext({})
export const UPDATE_COLOR = 'UPDATE_COLOR'
const reducer = (state, action) => {
    switch(action.type){
        case UPDATE_COLOR:
            return action.color
        default:
            return state
    }
}
export const Color = props => {
    const [color, dispatch] = useReducer(reducer, 'blue')
    return (
        <ColorContext.Provider value = {{color,dispatch}}>
            {props.children}
        </ColorContext.Provider>
    )
}
- 用 {props.children} 来显示子组件
- 将 color 和 dispatch 共享出去
showArea.js
import React , { useContext } from 'react';
import { ColorContext } from './color';
function ShowArea(){
    const { color } = useContext(ColorContext)
    return (<div style={{ color:color }}>字体颜色为{ color }</div>)
}
export default ShowArea
- 注意 引入 ColorContext 使用了大括号
Buttons.js
import React , { useContext } from 'react';
import { ColorContext, UPDATE_COLOR } from './color'
function Buttons(){
    const { dispatch } = useContext(ColorContext)
    return (
        <div>
            <button onClick={()=>{dispatch({type:UPDATE_COLOR,color:"red"})}}>红色</button>
            <button onClick={()=>{dispatch({type:UPDATE_COLOR,color:"yellow"})}}>黄色</button>
        </div>
    )
}
export default Buttons
Demo.js
import React, { useReducer } from 'react';
import ShowArea from './ShowArea';
import Buttons from './Buttons';
import { Color } from './color';   //引入Color组件
function Demo(){
    return (
        <>
            <Color>
                <ShowArea />
                <Buttons />
            </Color>
        </>
    )
}
export default Demo
useMemo
用来解决使用 React hooks 产生的无用渲染的性能问题。
import React , {useState,useMemo} from 'react';
function Demo(){
    const [xiaohong , setXiaohong] = useState('小红待客状态')
    const [zhiling , setZhiling] = useState('志玲待客状态')
    return (
        <>
            <button onClick={()=>{setXiaohong(new Date().getTime())}}>小红</button>
            <button onClick={()=>{setZhiling(new Date().getTime()+',志玲向我们走来了')}}>志玲</button>
            <ChildComponent name={xiaohong}>{zhiling}</ChildComponent>
        </>
    )
}
function ChildComponent({name,children}){
    function changeXiaohong(name){
        console.log('她来了,她来了。小红向我们走来了')
        return name+',小红向我们走来了'
    }
    const actionXiaohong = changeXiaohong(name)
    return (
        <>
            <div>{actionXiaohong}</div>
            <div>{children}</div>
        </>
    )
}
export default Demo
点击志玲按钮,小红对应的方法执行,虽然结果没变,但是每次都执行,损耗性能。
function ChildComponent({name,children}){
    function changeXiaohong(name){
        console.log('她来了,她来了。小红向我们走来了')
        return name+',小红向我们走来了'
    }
    const actionXiaohong = useMemo(()=>changeXiaohong(name),[name])
    return (
        <>
            <div>{actionXiaohong}</div>
            <div>{children}</div>
        </>
    )
}
第二个参数 [name] 匹配成功,才会执行。
useRef
- 用来获取React JSX中的DOM元素
- 用来保存变量
import React, { useRef} from 'react';
function Demo(){
    const inputEl = useRef(null)
        inputEl.current.value = "给 input value属性 赋值"
    return (
        <>
            <input ref={inputEl} type="text"/>
        </>
    )
}
export default Demo
import React, { useRef, useState, useEffect } from 'react'
function Demo(){
    const inputEl = useRef(null)
        inputEl.current.value="给 input value属性 赋值"
    const [text, setText] = useState('默认值')
    const textRef = useRef()
    useEffect(()=>{
        textRef.current = text
    })
    return (
        <>
            <input ref={inputEl} type="text"/>
            <input value={text} onChange={(e)=>{setText(e.target.value)}} />
        </>
    )
}
export default Demo
- text 每次发生变化,将值保存到 useRef 中
- 使用 useEffect 实现每次状态变化都进行变量重新赋值
- 很少用到这个功能(保存变量)
自定义 Hooks
编写自定义函数实现获取浏览器窗口
import React, { useState, useEffect, useCallback } from 'react';
function useWinSize(){
    const [ size , setSize] = useState({
        width:document.documentElement.clientWidth,
        height:document.documentElement.clientHeight
    })
    const onResize = useCallback(()=>{
        setSize({
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight
        })
    },[])
    useEffect(()=>{
        window.addEventListener('resize',onResize)
        return ()=>{
            window.removeEventListener('resize',onResize)
        }
    },[])
    return size;
}
function Demo(){
    const size = useWinSize()
    return (
        <div>页面Size:{size.width} x {size.height}</div>
    )
}
export default Demo
- 命名要使用 use 开头以确认该函数是自定义 Hook 而不是组件
- useCallback 用来缓存方法 ( useMemo 是为了缓存变量)
- 第一次进入方法时用 useEffect 来注册 resize 监听事件
- 防止一直监听所以在方法移除时,使用return的方式移除监听
- 最后在 Demo 组件中使用
文章参考
- 官方文档
- 哔哩哔哩up主技术胖的 视频
React Hooks 一步到位的更多相关文章
- 通过 React Hooks 声明式地使用 setInterval
		本文由云+社区发表 作者:Dan Abramov 接触 React Hooks 一定时间的你,也许会碰到一个神奇的问题: setInterval 用起来没你想的简单. Ryan Florence 在他 ... 
- 初探React Hooks & SSR改造
		Hooks React v16.8 发布了 Hooks,其主要是解决跨组件.组件复用的状态管理问题. 在 class 中组件的状态封装在对象中,然后通过单向数据流来组织组件间的状态交互.这种模式下,跨 ... 
- React hooks实践
		前言 最近要对旧的项目进行重构,统一使用全新的react技术栈.同时,我们也决定尝试使用React hooks来进行开发,但是,由于React hooks崇尚的是使用(也只能使用)function c ... 
- 理解 React Hooks
		欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由志航发表于云+社区专栏 TL;DR 一句话总结 React Hooks 就是在 react 函数组件中,也可以使用类组件(classe ... 
- React Hooks新特性学习随笔
		React Hooks 是 React 16.8 的新增特性.它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性. 前言 本篇主要以讲几个常用的api为主. 1.u ... 
- 关于React Hooks,你不得不知的事
		React Hooks是React 16.8发布以来最吸引人的特性之一.在开始介绍React Hooks之前,让咱们先来理解一下什么是hooks.wikipedia是这样给hook下定义的: In c ... 
- react hooks 全面转换攻略(三) 全局存储解决方案
		针对 react hooks 的新版本解决方案 一.redux维持原方案 若想要无缝使用原来的 redux,和其配套的中间件 promise,thunk,saga 等等的话 可以使用 redux-re ... 
- react新特性 react hooks
		本文介绍的是react新特性react hooks,本文面向的是有一定react开发经验的小伙伴,如果你对react还不是很熟悉的话我建议你先学习react并多多联系. 首先我们都知道react有3种 ... 
- 30分钟精通React今年最劲爆的新特性——React Hooks
		你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗? --拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function. 你还在为搞不清使用哪个生命周 ... 
随机推荐
- Spring Boot Thymeleaf 使用详解
			在上篇文章Spring Boot (二):Web 综合开发中简单介绍了一下 Thymeleaf,这篇文章将更加全面详细的介绍 Thymeleaf 的使用.Thymeleaf 是新一代的模板引擎,在 S ... 
- [转]C#操作Memcached帮助类
			在VS中安装Memcached,直接在NuGet下搜索Memcached,选择第一个进行安装: 服务端资源下载地址:https://pan.baidu.com/s/1gf3tupl 接下来开始写程序, ... 
- es6—变量的解构赋值
			数组的解构赋值 ]]]]]]] = []}} = {}} = {}})]: first]: last} = arr} = {}) {}))}))}) {}))}))].]]]])})] }}} = { ... 
- Codeforces Round #564 (Div. 2) D. Nauuo and Circle(树形DP)
			D. Nauuo and Circle •参考资料 [1]:https://www.cnblogs.com/wyxdrqc/p/10990378.html •题意 给出你一个包含 n 个点的树,这 n ... 
- H3C 链路聚合配置举例
- 2019-11-17-dotnet-core-使用-GBK-编码
			title author date CreateTime categories dotnet core 使用 GBK 编码 lindexi 2019-11-17 16:36:27 +0800 2019 ... 
- 【Kubernetes】容器集群管理常用命令笔记
			一.集群部署-查询集群状态 ①查询k8s master各组件健康状态: kubectl get componentstatus ②查询k8s node健康状态: kubectl get node 二. ... 
- Strongly Connected Tournament
			题解: 有一个很重要的性质就是 对于一张完全强联通图来说 一定有一个强联通分量入度为0(或者出度为0) 然后就一些计数题的基本套路 https://www.cnblogs.com/onioncyc/p ... 
- mapper的配置文件
			<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-// ... 
- 使用 Git和Github
			本地库初始化 git init 效果: 注意: .git 目录中存放的是本地库相关的子目录和文件,不要删除,也不要胡 乱修改. 设置签名 其实就是为了区分不同开发人员的身份需要设置一下自己的信息,包括 ... 
