React 16.13.1觸發兩次render


一段很普通的代碼,出發了兩次render

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

const MouseTracker: React.FC = () => {
  const [ positions, setPositions ] = useState({x: 0, y: 0})
  useEffect(() => {
    console.log('add effect', positions.x)
    const updateMouse= (e: MouseEvent) => {
      console.log('inner')
      setPositions({ x: e.clientX, y: e.clientY })
    }
    document.addEventListener('click', updateMouse)
    return () => {
      console.log('remove effect', positions.x)
      document.removeEventListener('click', updateMouse)
    }
  },[])
  console.log('before render', positions.x) // 執行了兩次
  return (
    <>
    <p>X: {positions.x}, Y : {positions.y}</p>
    </>
  )
}

export default MouseTracker

原因:

最近的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環境下不會這樣,所以不用擔心


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM