SoFunction
Updated on 2025-04-07

How to synchronously obtain state value in react (including hooks)

react (including hooks) synchronously get state value

environment

"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"
  },

Code Example

hooks

import {useState} from "react";
export default function Pre04SetStateSync() {
    const [counter, setCounter] = useState(0)
    const add = () => {
        setCounter(counter + 1)
        ({counter})
    }
    return <>
        <h3>synchronousSetState</h3>
        <p>Please observe the console</p>
        <button onClick={add}>counter: {counter}</button>
    </>
}

class 

export default class Pre04SetStateSync extends {
    state = {
        counter:0
    }
    add = () => {
        ({counter: + 1})
        ('~~',)
    }
    render() {
        return <>
            <h3>synchronousSetState</h3>
            <p>Please observe the console</p>
            <button onClick={}>counter: {}</button>
        </>
    }
}

The setCounter(xxx) in the hooks structure is equivalent to setState({counter: xxx}) in the class component writing method.

You can see that the counter output immediately after setCounter(setState) is the value of the previous time, and the button is displayed correctly, indicating that this update is asynchronous (react is designed to improve performance for batch updates). The counter has not had time to change when printing. If you need to get the latest value of the counter immediately after setting, you can achieve the synchronization effect as follows.

Asynchronous writing method

1. Write in setTimeout

Note that it only applies to class components

add = () => {
    setTimeout(()=>{
        ({counter: + 1})
        ('~~',)
    },0)
}

2. Synthetic events use native events to replace them

Note that it only applies to class components

// Native eventsexport default class Pre04SetStateSync extends  {
    state = {
        counter: 0
    }
    componentDidMount() {
        ('#btn').addEventListener('click', )
    }
    add = () => {
        ({counter:  + 1})
        ('~~', )
    }
    render() {
        return <>
            <h3>synchronousSetState</h3>
            <p>Please observe the console</p>
            <button id='btn'>counter: {}</button>
        </>
    }
}

3. Write to the callback function of setState

Note that it only applies to class components

export default class Pre04SetStateSync extends  {
    state = {
        counter: 0
    }
    add = () => {
        ({counter:  + 1}, ()=>{
            ('~~', )
        })
    }
    render() {
        return <>
            <h3>synchronousSetState</h3>
            <p>Please observe the console</p>
            <button onClick={}>counter: {}</button>
        </>
    }
}

4. The problem of continuous setState

Note that both class components and hooks are OK

If you change add to add 1 and then 2, you will find that the code only executes the last one plus 2, and adding 1 is ignored, such as:

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

The solution is to write the parameter of setState into a function form

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

5. Use side effects useEffect

Note, only for hooks

export default function Pre04SetStateSync() {
    const [counter, setCounter] = useState(0)
    const add = () => {
        setCounter(counter + 1)
    }
    useEffect(() => {
        ({counter})
    }, [counter])
    
    return <>
        <h3>synchronousSetState</h3>
        <p>Please observe the console</p>
        <button onClick={add}>counter: {counter}</button>
    </>
}

Common methods for react hooks

function Example01(){
    const [ count, setCount ] = useState(0)  //statement    return(
        <div>
            <p>{count}</p>  //Read            <button onClick={()=>setCount(count+1)}>count</button> // Use (modify)        </div>
    )
}

The useEffect function will be called once for the first rendering and each rendering afterwards. Before, we had to use two lifecycle functions to represent the re-render caused by the first rendering (componentDidMonut) and the update.

The execution of functions defined in the function will not hinder the browser from updating the view, that is, these functions are executed asynchronously, while the code in componentDidMonut and componentDidUpdate are executed synchronously.

Notice:

If there is no dependency after useEffect:

In this case, every time the page update will be executed

useEffect(()=>{
    ('implement');
})

If the following is empty

Execute once at the beginning of the page

useEffect(()=>{
    ('implement');
},[])

If there is a value after that and is not empty

It will only be triggered when the count changes

useEffect(()=>{
    ('implement');
},[count])

Use useEffect to unbind, when uninstalling components, such as clearing the timer, etc.:

However, when an empty array [] is passed, it is unbinding only when the component is to be destroyed, which implements the life cycle function of componentWillUnmount.

function Index() {
    useEffect(()=>{
        ('useEffect=>Index')
        return ()=>{
            ('Index page leaves')
        }
    },[])
    return <h2>Test unbinding</h2>;
}

Context value transmission

1. Parent component:

const CountContext = createContext()  //Introducefunction Example01(){
    const [ count, setCount ] = useState(0)
    return(
        <div>
            <p>{count}</p>
            <button onClick={()=>setCount(count+1)}>count</button>
            < value={count}>  //Pass the value using the wrapping subcomponent                <ChildContent/>
            </>      
        </div>
    )
}

2. Subcomponents:

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

It is also a function provided by React hooks, which can enhance our reducer and implement Redux-like functions.

import React, { useReducer  } from 'react'
function Example5(){
    const [ count, dispatch ] = useReducer((state,action)=&gt;{  
              switch(action){   //Check the corresponding action and execute the corresponding method            case 'add':
                return state+1
            case 'sub':
                return state-1
            default:
                return state
        }
    },1)
    return(
        &lt;div&gt;
            &lt;p&gt;{count}&lt;/p&gt;
            &lt;button onClick={()=&gt;dispatch('add')}&gt;add&lt;/button&gt;  //Through dispatch, pass the corresponding action and call the corresponding method            &lt;button onClick={()=&gt;dispatch('sub')}&gt;sub&lt;/button&gt;
        &lt;/div&gt;
    )
}
export default Example5

useMemo is mainly used to solve the performance problems of useless rendering generated by using React hooks.

Only when using useMemo and then passing the second parameter to her will it be executed.

1. In the parent component, pass the corresponding required parameters

import React , {useState,useMemo} from 'react';
function Example7(){
    const [one , setOne] = useState('The first state')
    const [two , setTwo] = useState('Chiling hospitality status')
    return (
        &lt;&gt;
            &lt;button onClick={()=&gt;{setOne(new Date().getTime())}}&gt;The first&lt;/button&gt;
            &lt;button onClick={()=&gt;{setTwo(new Date().getTime())}}&gt;The second one&lt;/button&gt;
            &lt;ChildComponent name={one}&gt;{two}&lt;/ChildComponent&gt;
        &lt;/&gt;
    )
}

2. Parent component calls child component

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

Use useRef to get the DOM element in React JSX, and after obtaining it, you can control anything in the DOM. However, this is not recommended. Changes in the React interface can be controlled through state

import React, { useRef } from 'react'
function Example8(){
    const inputRef  = useRef(null)
    const onButtonClick=()=&gt;{
        ='THIS IS INPUT'
        (inputRef);
    }
    return(
        &lt;div&gt;
            &lt;input type="text" ref={inputRef}/&gt;
            &lt;button onClick = {onButtonClick}&gt;show&lt;/button&gt;
        &lt;/div&gt;
    )
}
export default Example8

Save normal variables

import React, { useRef,useState } from 'react'
function Example8(){
    const inputRef  = useRef(null)
    const onButtonClick=()=&gt;{
        ='THIS IS INPUT'
        (inputRef);
    }
     const [state, setstate] = useState('inputValue')  //Declare a variable    return(
        &lt;div&gt;
            &lt;input type="text" ref={inputRef}/&gt;
            &lt;button onClick = {onButtonClick}&gt;show&lt;/button&gt;
            &lt;input value={state} type="text" onChange={(e)=&gt;setstate()}/&gt;  //Bind the corresponding value and bind the onChange event        &lt;/div&gt;
    )
}
export default Example8

The above is personal experience. I hope you can give you a reference and I hope you can support me more.