react中(含hooks)同步获取state值的方式

 更新时间:2022年08月08日 10:34:04   作者:daoke_li  
这篇文章主要介绍了react(含hooks)中同步获取state值的方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

react(含hooks)同步获取state值

环境

"dependencies": {
    "babel-plugin-transform-decorators-legacy": "^1.3.5",
    "customize-cra": "^1.0.0",
    "rc-form": "^2.4.11",
    "react": "^17.0.1",
    "react-app-rewired": "^2.1.8",
    "react-dom": "^17.0.1",
    "react-router-dom": "^5.2.0",
    "react-scripts": "^4.0.1",
    "redux": "^4.0.5"
  },

代码示例

hooks

import {useState} from "react";
export default function Pre04SetStateSync() {
    const [counter, setCounter] = useState(0)
    const add = () => {
        setCounter(counter + 1)
        console.log({counter})
    }
    return <>
        <h3>同步SetState</h3>
        <p>请观察控制台</p>
        <button onClick={add}>counter: {counter}</button>
    </>
}

class 

export default class Pre04SetStateSync extends React.Component{
    state = {
        counter:0
    }
    add = () => {
        this.setState({counter:this.state.counter + 1})
        console.log('~~this.state.counter',this.state.counter)
    }
    render() {
        return <>
            <h3>同步SetState</h3>
            <p>请观察控制台</p>
            <button onClick={this.add}>counter: {this.state.counter}</button>
        </>
    }
}

hooks结构中的setCounter(xxx)相当于class组件写法中setState({counter: xxx})

可以对比控制台看到,这样直接setCounter(setState)后立即输出的counter的是上一次的值,而按钮上显示正确,说明本次更新是异步的(react这样设计是为了批量更新而提高性能),打印时counter还没来得及改变。如果需要set完后立即取到counter的最新值,可以按如下方法实现同步的效果。

异步写成同步的方法

1. 写在setTimeout中

注意,只适用于class组件

add = () => {
    setTimeout(()=>{
        this.setState({counter:this.state.counter + 1})
        console.log('~~this.state.counter',this.state.counter)
    },0)
}

2. 合成事件使用原生事件替代

注意,只适用于class组件

// 原生事件
export default class Pre04SetStateSync extends React.Component {
    state = {
        counter: 0
    }
    componentDidMount() {
        document.querySelector('#btn').addEventListener('click', this.add)
    }
    add = () => {
        this.setState({counter: this.state.counter + 1})
        console.log('~~this.state.counter', this.state.counter)
    }
    render() {
        return <>
            <h3>同步SetState</h3>
            <p>请观察控制台</p>
            <button id='btn'>counter: {this.state.counter}</button>
        </>
    }
}

3. 写入setState的回调函数中

注意,只适用于class组件

export default class Pre04SetStateSync extends React.Component {
    state = {
        counter: 0
    }
    add = () => {
        this.setState({counter: this.state.counter + 1}, ()=>{
            console.log('~~this.state.counter', this.state.counter)
        })
    }
    render() {
        return <>
            <h3>同步SetState</h3>
            <p>请观察控制台</p>
            <button onClick={this.add}>counter: {this.state.counter}</button>
        </>
    }
}

4. 连续setState的问题

注意,class组件和hooks都可以

如果将add改为先加1再加2,会发现代码只执行了最后一个加2,加1被忽略了,如:

const add = () => {
    setCounter(counter + 1)
    setCounter(counter + 2)
}

解决方法是将setState的参数写成函数形式

const add = () => {
    setCounter(counter => counter + 1)
    setCounter(counter => counter + 2)
}

5. 使用副作用useEffect

注意,只适用于hooks

export default function Pre04SetStateSync() {
    const [counter, setCounter] = useState(0)
    const add = () => {
        setCounter(counter + 1)
    }
    useEffect(() => {
        console.log({counter})
    }, [counter])
    
    return <>
        <h3>同步SetState</h3>
        <p>请观察控制台</p>
        <button onClick={add}>counter: {counter}</button>
    </>
}

react hooks常用方法

1.useState

function Example01(){
    const [ count, setCount ] = useState(0)  //声明
    return(
        <div>
            <p>{count}</p>  //读取
            <button onClick={()=>setCount(count+1)}>计数</button> // 使用(修改)
        </div>
    )
}

2.useEffect

1.React首次渲染和之后的每次渲染都会调用一遍useEffect函数,而之前我们要用两个生命周期函数分别表示首次渲染(componentDidMonut)和更新导致的重新渲染(componentDidUpdate)

2.useEffect中定义的函数的执行不会阻碍浏览器更新视图,也就是说这些函数时异步执行的,而componentDidMonut和componentDidUpdate中的代码都是同步执行的。

注意:

如果useEffect后面没有依赖:

这种时候每次每次页面更新都会执行

useEffect(()=>{
    console.log('执行');
})

如果后面为空

页面初始的时候执行一次

useEffect(()=>{
    console.log('执行');
},[])

如果后面有值且不为空

只有当count改变时才会被触发

useEffect(()=>{
    console.log('执行');
},[count])

使用useEffect解绑,组件卸载的时候,比如需要清除计时器等:

但是当传空数组[]时,就是当组件将被销毁时才进行解绑,这也就实现了componentWillUnmount的生命周期函数。

function Index() {
    useEffect(()=>{
        console.log('useEffect=>Index')
        return ()=>{
            console.log('Index页面离开')
        }
    },[])
    return <h2>测试解绑</h2>;
}

3.useContext上下文传值

1.父组件:

const CountContext = createContext()  //引入
function Example01(){
    const [ count, setCount ] = useState(0)
    return(
        <div>
            <p>{count}</p>
            <button onClick={()=>setCount(count+1)}>计数</button>
            <CountContext.Provider value={count}>  //使用包裹子组件传递值
                <ChildContent/>
            </CountContext.Provider>      
        </div>
    )
}

2.子组件:

function ChildContent(){
     const context = useContext(CountContext) 
     return(
         <p>{context}</p>
     )
}

4.useReducer

它也是React hooks提供的函数,可以增强我们的Reducer,实现类似Redux的功能。

import React, { useReducer  } from 'react'
function Example5(){
    const [ count, dispatch ] = useReducer((state,action)=>{  
              switch(action){   //通过判断对应的action,去执行对应的方法
            case 'add':
                return state+1
            case 'sub':
                return state-1
            default:
                return state
        }
    },1)
    return(
        <div>
            <p>{count}</p>
            <button onClick={()=>dispatch('add')}>add</button>  //通过dispatch,传递对应的action,调用对应的方法
            <button onClick={()=>dispatch('sub')}>sub</button>
        </div>
    )
}
export default Example5

5.useMemo

useMemo主要用来解决使用React hooks产生的无用渲染的性能问题。

只要使用useMemo,然后给她传递第二个参数,参数匹配成功,才会执行。

1.在父组件里面,传递对应需要的参数

import React , {useState,useMemo} from 'react';
function Example7(){
    const [one , setOne] = useState('第一个的状态')
    const [two , setTwo] = useState('志玲待客状态')
    return (
        <>
            <button onClick={()=>{setOne(new Date().getTime())}}>第一个</button>
            <button onClick={()=>{setTwo(new Date().getTime())}}>第二个</button>
            <ChildComponent name={one}>{two}</ChildComponent>
        </>
    )
}

2.父组件调用子组件

function ChildComponent({name,children}){
    function changeXiaohong(name){
        return name
    }
 const actionXiaohong = useMemo(()=>changeXiaohong(name),[name])
    return (
        <>
            <div>{actionXiaohong}</div>
            <div>{children}</div>
        </>
    )
}

6.useRef

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

import React, { useRef } from 'react'
function Example8(){
    const inputRef  = useRef(null)
    const onButtonClick=()=>{
        inputRef.current.value='THIS IS INPUT'
        console.log(inputRef);
    }
    return(
        <div>
            <input type="text" ref={inputRef}/>
            <button onClick = {onButtonClick}>显示</button>
        </div>
    )
}
export default Example8

保存普通变量

import React, { useRef,useState } from 'react'
function Example8(){
    const inputRef  = useRef(null)
    const onButtonClick=()=>{
        inputRef.current.value='THIS IS INPUT'
        console.log(inputRef);
    }
     const [state, setstate] = useState('inputValue')  //声明一个变量
    return(
        <div>
            <input type="text" ref={inputRef}/>
            <button onClick = {onButtonClick}>显示</button>
            <input value={state} type="text" onChange={(e)=>setstate(e.target.value)}/>  //绑定对应的值以及绑定onChange事件
        </div>
    )
}
export default Example8

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • React Hooks的深入理解与使用

    React Hooks的深入理解与使用

    这篇文章主要介绍了React Hooks的深入理解与使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • React Native react-navigation 导航使用详解

    React Native react-navigation 导航使用详解

    本篇文章主要介绍了React Native react-navigation 导航使用详解,详解的介绍了react-navigation导航的使用,具有一定的参考价值,有兴趣的可以了解一下
    2017-12-12
  • JavaScript中的useRef 和 useState介绍

    JavaScript中的useRef 和 useState介绍

    这篇文章主要给大家分享的是 JavaScript中的useRef 和 useState介绍,下列文章,我们将学习 useRef 和 useState hook是什么,它们的区别以及何时使用哪个。 这篇文章中的代码示例将仅涉及功能组件,但是大多数差异和用途涵盖了类和功能组件,需要的朋友可以参考一下
    2021-11-11
  • React列表栏及购物车组件使用详解

    React列表栏及购物车组件使用详解

    这篇文章主要为大家详细介绍了React列表栏及购物车组件使用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • 详解React Hooks是如何工作的

    详解React Hooks是如何工作的

    React Hooks是在React 16.8版本新增的特性,在我看了React官网和一些博客对React Hook的讲解后还是觉得没有get到本质。本篇博客通过手动实现useState()来了解Hook的原理和本质。阅读此篇博客的前提是你要知道一些 React Hooks的基本用法和使用规则,不然会看得云里雾里。
    2021-05-05
  • React学习笔记之高阶组件应用

    React学习笔记之高阶组件应用

    这篇文章主要介绍了React 高阶组件应用,详细的介绍了什么是React高阶组件和具体使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • React中代码分割的4种实现方式

    React中代码分割的4种实现方式

    虽然一直有做react相关的优化,按需加载、dll 分离、服务端渲染,但是从来没有从路由代码分割这一块入手过,所以下面这篇文章主要给大家介绍了关于React中代码分割的4种实现方式,需要的朋友可以参考下
    2022-01-01
  • React Native实现地址挑选器功能

    React Native实现地址挑选器功能

    这篇文章主要为大家详细介绍了React Native仿地址挑选器功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 详解一个基于react+webpack的多页面应用配置

    详解一个基于react+webpack的多页面应用配置

    这篇文章主要介绍了详解一个基于react+webpack的多页面应用配置,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • React日期时间显示组件的封装方法

    React日期时间显示组件的封装方法

    这篇文章主要为大家详细介绍了React日期时间显示组件的封装方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08

最新评论