首页 > 解决方案 > 反应功能和类组件是否呈现不同?

问题描述

当我使用带有一些状态管理器的反应功能组件(我正在使用recoil.js)并尝试使用反应挂钩更新状态时,它仅在状态与原始状态不同时才调用useEffect。当我在讨论组件如何重新呈现的堆栈溢出时,他们正在谈论类组件,以及每次调用 setState 时它们如何呈现。这只是两个组件类型工作方式之间的区别还是我只是误解了它?

这是我对功能组件的代码测试:

import React, {useEffect} from 'react'
import ReactDOM from 'react-dom'
import {atom, useRecoilState, RecoilRoot} from 'recoil'

ReactDOM.render(
    <React.StrictMode>
        <RecoilRoot>
            <App />
        </RecoilRoot>
    </React.StrictMode>,
    document.getElementById('root')
);

const testAtom = atom({
    key: "test",
    default: ""
});

function App(){
    return (
        <>
            <C1 />
            <C2 />
        </>
    );
}

function C1(){
    const [test, setTest] = useRecoilState(testAtom);
    
    useEffect(() => {
        console.log('effected', 'c1');
    });
    
    return (
        <div>
            <button onClick={() => {setTest('c1')}}>Click me</button>
        </div>
    );
}

function C2(){
    const [test, setTest] = useRecoilState(testAtom);
    
    useEffect(() => {
        console.log('effected', 'c2');
    });
    
    return (
        <div>
            <button onClick={() => {setTest('c2')}}>Click me</button>
        </div>
    );

}

运行这个 useEffect 只在状态改变的时候被调用,而不只是在 setTest 被调用的时候,这个人对类组件说的不是这样。

React 不比较状态数据。当调用 setState 时,它​​会将组件标记为脏(这意味着它需要重新渲染)。

这是否意味着如果我要将它作为一个类组件,它每次都会 conoslelog?

标签: javascriptreactjsrecoiljs

解决方案


是和不是。我不会说“它们以不同的方式呈现”,但是在确定何时重新呈现组件的方式之间存在差异。我理解人们如何期望默认行为是相同的,但是,我也理解引入新的状态系统 ( useState) 为开发人员提供了改进默认行为的机会。

我不知道反冲具体是如何工作的,但我认为它的行为至少类似于useState重新渲染组件。从文档中:

如果您将 State Hook 更新为与当前状态相同的值,React 将退出而不渲染子级或触发效果。(React 使用Object.is 比较算法。)

所以这证实了你的观察。

但是让我明确一点:这不是功能组件的特性,它就是这样useState工作的。您可以开发自己的行为不同的状态管理钩子。

class现在从setState文档中寻找添加组件:

setState()shouldComponentUpdate()除非返回,否则总是会导致重新渲染false

关于shouldComponentUpdate

用于shouldComponentUpdate()让 React 知道组件的输出是否不受当前状态或道具变化的影响。默认行为是在每次状态更改时重新渲染,并且在绝大多数情况下,您应该依赖默认行为。

shouldComponentUpdate()当接收到新的道具或状态时,在渲染之前调用。默认为true.

第一部分不是很清楚(“默认行为是在每次状态更改时重新渲染”,但是是否将相同的值设置为“更改”?),但第二段说明了这一点。shouldComponentUpdate默认返回true,所以组件在setState被调用时总是会重新渲染。

如果您实施shouldComponentUpdateto callObject.is您将复制useState.


推荐阅读