【React阶段二 分支二 React hook】1、Reack hooks模式 & ES6(技术胖)

350 阅读6分钟

知识体系四:可能很多写法已经过时 不用跟着敲,看第五篇结合官方demo 文章定位:使用useState等方法构建无状态函数组件,不走Redux流程;

一、实践笔记来自:React Hooks 免费视频教程(共11集) (jspang.com)

  • 特征:用函数的形式代替原来的继承类的形式,并且使用预函数的形式管理state
  • 有状态组件和无状态组件都可以使用函数式function,不用extends Component;
  • 代替以前的redux写法

第一节 React Hooks介绍和环境搭建

  1. 计数器conut与对应set方法 hooks的useState设置与改变状态
import React, { useState } from 'react';
function Example(){

    const [ count , setCount ] = useState(0);
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count+1)}}>click me</button>
        </div>
    )
}
export default Example;

第二节 useState介绍与多状态声明

1、useState是react自带的一个hook函数,它的作用是用来声明状态变量。

  • 数组解构,建立映射 并确定从0开始
  • useState(0)地址对应count,useState(1)对应setCount
  • 此时代码中通过{count}可以直接拿到值

2、 多状态声明

    const [ age , setAge ] = useState(18)
    const [ sex , setSex ] = useState('男')
    const [ work , setWork ] = useState('前端程序员')
    return (
        <div>
            <p>JSPang 今年:{age}岁</p>
            <p>性别:{sex}</p>
            <p>工作是:{work}</p>

        </div>
    )

第三节 useEffect代替常用生命周期函数(异步)

//首次渲染生命周期
componentDidMount(){ console.log(`ComponentDidMount=>You clicked ${this.state.count} times`) } 
//第二次渲染生命周期
componentDidUpdate(){ console.log(`componentDidUpdate=>You clicked ${this.state.count} times`) }
//首次与第二次渲染生命周期都会走这个
useEffect(()=>{ console.log(`useEffect=>You clicked ${count} times`) })

第四节 useEffect 实现 componentWillUnmount生命周期函数解绑

  • 渲染销毁时的生命周期:启用第二参数【当前状态值变化时触发生命周期,传[]为销毁时解绑,会执行return方法】
  • 传空数组时就可以触发useEffect组件将被销毁时才进行解绑
  • 比较有意思的是 传[count]后count变化这个就会触发
function Index() {
    useEffect(()=>{
        console.log('useEffect=>老弟你来了!Index页面')
        return ()=>{
            console.log('老弟,你走了!Index页面')
        }
    },[])
    return <h2>JSPang.com</h2>;
}

第五节 useContext 让父子组件传值更简单[useContextuseReducer]

1、问题原因:在用类声明组件时,父子组件的传值是通过组件属性和props进行的,那现在使用方法(Function)来声明组件,已经没有了constructor构造函数也就没有了props的接收,那父子组件的传值就成了一个问题

2、 useContextredux的作用是不同的,一个解决的是组件之间值传递的问题,一个是应用中统一管理状态的问题,但通过和useReducer的配合使用,可以实现类似Redux的作用

3、 实践

  1. 定义createContext对象,通过Provider展开value,允许跨层级实现传递和使用了(也就是实现了上下文),当父组件的count变量发生变化时,子组件也会发生变化
  2. 补充好文:React Hooks 系列之3 useContext
import React, { useState , createContext } from 'react';
//===关键代码
const CountContext = createContext()

function Example4(){
    const [ count , setCount ] = useState(0);

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count+1)}}>click me</button>
            {/*======关键代码 */}
            <CountContext.Provider value={count}>
            </CountContext.Provider>

        </div>
    )
}
export default Example4;
  1. 使用useContext接收传递过来的对象即可
function Counter(){
    const count = useContext(CountContext)  //一句话就可以得到count
    return (<h2>{count}</h2>)
}
  1. 留意,这个是在同个文件夹中写个子组件取值

image.png

第六节 useReducer增强reducer

  • useReducer参数1:reducer函数 参数2:状态初始值,会返回两个值
  • const定义数组接收两个值,第一个是return的值,第二个是lambda派发器的地址
import React, { useReducer } from 'react';

function ReducerDemo(){
    const [ count , dispatch ] =useReducer((state,action)=>{
        switch(action){
            case 'add':
                return state+1
            case 'sub':
                return state-1
            default:
                return state
        }
    },0)
    return (
       <div>
           <h2>现在的分数是{count}</h2>
           <button onClick={()=>dispatch('add')}>Increment</button>
           <button onClick={()=>dispatch('sub')}>Decrement</button>
       </div>
    )

}

export default ReducerDemo

第七,八节 useReducer代替Redux小案例

1、 useContext共享值

  • useContext:可访问全局状态,避免一层层的传递状态。这符合Redux其中的一项规则,就是状态全局化,并能统一管理。
  • useReducer:通过action的传递,更新复杂逻辑的状态,主要是可以实现类似Redux中的Reducer部分,实现业务逻辑的可行性。
  1. 里面的共享颜色组件
  • 我去这种写法还能嵌套也是服了,这tm还能传子组件。。因为要确定类型直接用这个:props.children。。强
import React, { createContext } from 'react';

export const ColorContext = createContext({})

export const Color = props=>{
    return (
        <ColorContext.Provider value={{color:"blue"}}>
            {props.children}
        </ColorContext.Provider>
    )
}

image.png

2、使用useReducer管管理事件分发

image.png

第九节 useMemo优化React Hooks程序性能

1、问题:以前讲过TODOList的时候 讲道理shouldCompnentUpdate可以制止父组件更新时的子组件更新,现在 hook不再区分mountupdate两个状态

  • 解决方案:useMemo(缓存属性/状态)useCallback(缓存方法)都是解决上述性能问题的

2、 案例:父组件有发生变化时,所有子组件都会执行,这边点击运行就会给赋值一个新的时间戳,点第二个的时候,小红时间戳没变但也执行了

image.png

  1. 使用useMemo() ()=>changeXiaohong(name),[name]
  • 第一个参数是个函数(用个箭头表达式子表面是函数 没左边那个是个方法结果) ()=>changeXiaohong(name)
  • 第二个参数是观察对象,当观察对象发生变化时执行这个函数,name是 <ChildComponent name={xiaohong}>{zhiling}</ChildComponent>传过来的小红对象,此时点小红才会执行。

第十节 useRef获取DOM元素和保存变量

1、作用

  • useRef获取React JSX中的DOM元素,获取后你就可以控制DOM的任何东西了。但是一般不建议这样来作,React界面的变化可以通过状态来控制。

image.png

  • useRef来保存变量,这个在工作中也很少能用到,我们有了useContext这样的保存其实意义不大,可以了解一下。

第十一节 自定义Hooks函数获取窗口大小[默认use开头]

1、导包

import React, { useState ,useEffect ,useCallback } from 'react';

2、编写函数

  1. 通过useState暴露属性
  2. useCallback(缓存方法)进行优化
  3. 渲染时声明监听'resize'屏幕发生尺寸变化,监听view解绑时销毁监听
function useWinSize(){
    //size对象{width,width}
    const [ size , setSize] = useState({
        width:document.documentElement.clientWidth,
        height:document.documentElement.clientHeight
    })
    
    //定义setSize方法  使用useCallback包裹 并返回给onResize对象
    const onResize = useCallback(()=>{
        setSize({
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight
        })
    },[]) 
    
    //使用生命周期  渲染的时候执行onResize对象对应的方法
    useEffect(()=>{
        window.addEventListener('resize',onResize)
        //使用return  方法销毁时解绑,取消监听
        return ()=>{
            window.removeEventListener('resize',onResize)
        }
    },[])

    return size;

}
  1. 编写组件
function Example9(){

    const size = useWinSize()
    return (
        <div>页面Size:{size.width}x{size.height}</div>
    )
}

export default Example9 
  1. Index.js引入即可看到页面大小,此时拖拽页面大小即可看到效果。

补充知识

一、 ES6语法

1、三种声明方式 var,let,const

1、 var为全局声明

var a=2;
{
   var a=3;
}
console.log(a);//a=3
  1. let局部变量声明,出作用域立刻失效;
  • 循环体内也很好用
for(let i=0;i<10;i++){ console.log('循环体中:'+i); } 
  1. const声明常量

2、变量解构赋值

1、 数组的结构赋值

  1. 常见写法:letl [a,b,c]=[1,2,3];

  2. 允许默认值: let [a,b="JSPang"]=['技术胖'] console.log(a+b); //控制台显示“技术胖JSPang”

  3. 注意的是undefined和null,undefined是啥都不干,相当于2中的写法(多参情况就好用),null是赋为null。

2、对象的解构赋值:String类型,对象外面用花括号

  1. 直接定义
let {foo,bar} = {foo:'JSPang',bar:'技术胖'};
console.log(foo+bar); //控制台打印出了“JSPang技术胖
  1. 若对象已声明,需要用圆括号全包裹
let foo;
({foo} ={foo:'JSPang'});
console.log(foo); //控制台输出jspang

3、 字符串解构:const [a,b,c,d,e,f]="JSPang";

二、 其他

  1. 带你学懂Redux-上篇 - 掘金 (juejin.cn)
  2. React当中的Hooks - 掘金 (juejin.cn)