React 16.13.1使用useState時會執行兩次render的問題

示例使用typescript編寫一個簡單的hello

新建一個Hello.tsx組件:

import React, {useState} from 'react'


interface IHelloProps {
    message?: string;
}
const Hello: React.FC<IHelloProps> = (props) => {
    console.log('hello before render....')
    return (
        <h2>
            {props.message}
        </h2>
    )
}

export default Hello

Hello.defaultProps = {
    message: 'what the fuck'
}

觀察控制檯輸出,會發現,hello before render....只輸出一次。

繼續往hello組件中添加count狀態

import React, {useState} from 'react'


interface IHelloProps {
    message?: string;
}
const Hello: React.FC<IHelloProps> = (props) => {
    const [count, setCount] = useState(0)

    console.log('hello before render....')
    return (
        <h2>
            {props.message}
            <div>點擊次數{count}</div>
        </h2>
    )
}

export default Hello

Hello.defaultProps = {
    message: 'what the fuck'
}

觀察控制檯輸出,會發現hello before render....輸出了兩次,

繼續往hello添加點擊事件:

import React, {useState} from 'react'


interface IHelloProps {
    message?: string;
}
const Hello: React.FC<IHelloProps> = (props) => {
    const [count, setCount] = useState(0)

    console.log('hello before render....')
    return (
        <h2>
            {props.message}
            <div
                onClick={() => {
                    setCount(count + 1)
                }}
            >
                點擊次數{count}
            </div>
        </h2>
    )
}

export default Hello

Hello.defaultProps = {
    message: 'what the fuck'
}

觀察控制檯輸出,會發現初始化的時候,hello before render....執行了兩次,每次點擊的時候,hello before render....都輸出了兩次。

這個問題產生的原因是啥,可以從https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects找到答案

原因:

最近的react版本,dev模式下render使用的是strict mode,strict mode的通過兩次調用constructor和render函數來更好的檢測不符合預期的side effects

文檔中有表明

Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:

  • Class component constructor, render, and shouldComponentUpdate methods
  • Class component static getDerivedStateFromProps method
  • Function component bodies
  • State updater functions (the first argument to setState)
  • Functions passed to useState, useMemo, or useReducer

下列函數會執行兩次

  • 類組件的constructor,render和shouldComponentUpdate方法
  • 類組建的靜態方法getDerivedStateFromProps
  • 函數組件方法體
  • 狀態更新函數(setState的第一個參數)
  • 傳入useState,useMemo或useReducer的函數

在production環境下不會這樣,所以不用擔心

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章