zoukankan      html  css  js  c++  java
  • 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({
            document.documentElement.clientWidth,
            height:document.documentElement.clientHeight
        })
    
        const onResize = useCallback(()=>{
            setSize({
                 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主技术胖的 视频
  • 相关阅读:
    k3sk8s集群-node节点设置不可调度或者删除node节点
    CentOS8防暴力破解fail2ban
    网站挂马情况处理
    linux给普通用户赋予sudo权限免密码
    Mockito (二十四)
    Mockito (二十三)
    Mockito (二十二)
    Mockito (二十一)
    Mockito (二十)
    Mockito (十九)
  • 原文地址:https://www.cnblogs.com/guangzan/p/12210806.html
Copyright © 2011-2022 走看看