【问题标题】:Do I have to worry about useState causing a re-render?我是否必须担心 useState 会导致重新渲染?
【发布时间】:2020-12-23 09:42:32
【问题描述】:

注意:我在 wordpress.stackexchange 上问过这个问题,但那里没有得到任何回应,所以在这里尝试。

我不确定这是 WordPress 特有的,WordPress 的重载 React 特有的,还是仅仅是 React,但我正在为 WordPress 创建一个新的块插件,如果我在其 edit 函数中使用 useState,即使我从未调用 setter 函数,页面也会重新呈现。

import { useState } from '@wordpress/element';

export default function MyEdit( props ) {
        const {
                attributes: {
                    anAttribute
                },
                setAttributes,
        } = props;

        const [ isValidating, setIsValidating ] = useState( false );
        const post_id = wp.data.select("core/editor").getCurrentPostId();
        console.log('Post ID is ', post_id);

        const MyPlaceholder = () => {
            return(
                <div>this is a test</div>
            );
        };

        const Component = MyPlaceholder;

        return <Component />;
}

如果我注释掉const [ isValidating, setIsValidating ] = useState( false );,那么console.log 会发生一次。如果我把它留在里面,它会发生两次;即使我从不检查isValidating 的值,也不要介意打电话给setIsValidating。我不想过度优化事物,但同样,如果我在页面上使用此块 n 次,则该页面将呈现 2n 次。它只是在管理方面,因为它在edit 中,所以也许没什么大不了的,但是......它似乎不对。这是useState 的预期行为吗?难道我做错了什么?我是否需要担心(从速度的角度,从潜在的竞争条件,因为一切都重新渲染多次)?

【问题讨论】:

  • 如果你得到答案,请接受
  • 现在就在玩你的答案——一旦我确认它有效,我肯定会接受!
  • 肯定感谢更新,请告诉我,以便我能提供更多帮助

标签: reactjs wordpress use-state wordpress-gutenberg


【解决方案1】:

在您的示例代码中,每次都会立即评估 console.log 语句并触发块的重绘/重新渲染。一旦console.log 被移除,只有状态变化会触发重新渲染。

由于 Gutenberg 编辑器基于 Redux,如果状态发生变化,任何依赖于该状态的组件都会重新渲染。当一个块在编辑器中选择时,被选择的块被同步渲染,而编辑器中的所有其他块被异步渲染。 WordPress Gutenberg 开发人员意识到重新渲染是 performance concern,并已采取措施减少重新渲染。

从 wp.data 请求数据时,应使用useEffect() 来安全地等待异步数据:

import { useState, useEffect } from '@wordpress/element';

    export default function MyEdit(props) {
    ...
    const [curPostId, setCurPostId] = useState(false);

    useEffect(() => {
        async function getMyPostId() {
            const post_id = await wp.data.select("core/editor").getCurrentPostId();
            setCurPostId(post_id);
        }
        getMyPostId();
    }, []); // Run once

    const MyPlaceholder = () => {
        return (
             <div>Current Post Id: {curPostId}</div>
        );
    };

    const Component = MyPlaceholder;

    return <Component />;
}

如问题中所述,useState() 在核心块中用于设置和更新状态。状态钩子是在 React 16.8 中引入的,这是一个相当新的变化,您可能会遇到旧的 Gutenberg 代码示例,它通过类构造函数设置状态并且不使用钩子。

【讨论】:

    【解决方案2】:

    是的,你必须担心总是放置一个依赖数组,这样它就不会重新渲染,根据你的查询,假设你计划编辑一个字段这里是示例代码

    const [edit, setEdit]= useState(props);
    
    useEffect(() => {
    // logic here
    },[edit])
    

    [edit] 将检查是否有任何更改,并据此更新 DOM,如果您不放置任何 [](依赖项数组),它将始终进入无限循环,

    【讨论】:

    • 嗯。我不认为这是完全的。首先,如果我添加一个useEffect,它里面的东西确实只发生了一次,但是页面仍然被渲染了两次(或者,至少,MyEdit 函数被调用了两次)。其次,在 WordPress 核心块中有很多使用 useState 而不使用 useEffect 的示例(例如,按钮、html、社交链接等)。
    • 使用 async await 编写函数并将其绑定在 useEffect 中,我不确定 Wordpress 但试一试,使用 useState 不是您重新渲染的问题,您错过了某个地方,
    【解决方案3】:

    我猜这是预期的行为。如果我在使用useState 的本机核心块中添加类似的console.log,我会得到相同的效果。似乎 WordPress 使用use strict 运行,根据this answer,React 在严格模式下会双重调用许多东西。

    【讨论】:

      猜你喜欢
      • 2020-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 2019-05-02
      • 1970-01-01
      相关资源
      最近更新 更多