You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Gutenberg区块中getEntityRecord总是使用hikeId的旧值?

问题

在编辑器中输入hikeId时,useSelect始终给getEntityRecord传入之前的旧值,而非当前输入的新值。我原本以为给useSelect设置依赖项[hikeId]后,React会在hikeId变化时重新执行它,但实际没生效。请问该怎么改代码,让distance、duration和ascend能通过当前的hikeId获取对应数据?

原代码:

import { useBlockProps } from '@wordpress/block-editor';
import { TextControl } from '@wordpress/components';

const { useSelect } = wp.data;

const HikeSummaryData = ( props ) => {
    const {
        attributes: { hikeId, distance, duration, ascend },
        setAttributes,
    } = props;

    const postData = useSelect(select => {
        return hikeId
            ? select('core').getEntityRecord('postType', 'post', hikeId)
            : undefined;
    }, [ hikeId ]);

    const determineData = (value) => {
        setAttributes({
            hikeId: value,
            distance: postData && postData.meta ? postData.meta['alsnuff_hike_summary_distance_meta'] : -1,
            duration: postData && postData.meta ? postData.meta['alsnuff_hike_summary_duration_meta'] : -1,
            ascend: postData && postData.meta ? postData.meta['alsnuff_hike_summary_ascend_meta'] : -1
        });
    };

    return (
        <div {...useBlockProps()}>
            <fieldset>
                <legend>Hike ID</legend>
                <TextControl
                    value={ hikeId }
                    onChange={ determineData }
                />
            </fieldset>

            <div class="card">
                <footer class="card-footer">
                    <a href="#" class="card-footer-item">Distanz: { distance != -1 ? (Math.floor(distance / 100) / 10) + 'km' : '-' }</a>
                    <a href="#" class="card-footer-item">Dauer: { duration != -1 ? duration + 'h' : '-' }</a>
                    <a href="#" class="card-footer-item">Aufstieg: { ascend != -1 ? ascend + 'm' : '-' }</a>
                </footer>
            </div>
        </div>
    );
};

export default HikeSummaryData;
解决方案

核心问题是:determineData里的postData是闭包捕获的旧值——useSelect获取新数据是异步操作,不会在你修改hikeId的同步步骤里立刻更新postData。所以你在onChange里直接用postData设置其他属性,拿到的必然是旧数据。

修改思路:

  1. 让onChange只负责更新hikeId,不要同步处理其他属性
  2. 用useEffect监听postData的变化,当新的postData加载完成后,再更新distance、duration和ascend

修改后的代码:

import { useBlockProps } from '@wordpress/block-editor';
import { TextControl } from '@wordpress/components';
import { useEffect } from '@wordpress/element'; // 新增导入useEffect

const { useSelect } = wp.data;

const HikeSummaryData = ( props ) => {
    const {
        attributes: { hikeId, distance, duration, ascend },
        setAttributes,
    } = props;

    const postData = useSelect(select => {
        return hikeId
            ? select('core').getEntityRecord('postType', 'post', hikeId)
            : undefined;
    }, [ hikeId ]);

    // 监听postData变化,同步更新属性
    useEffect(() => {
        if (!postData?.meta) return;
        
        setAttributes({
            distance: postData.meta['alsnuff_hike_summary_distance_meta'] || -1,
            duration: postData.meta['alsnuff_hike_summary_duration_meta'] || -1,
            ascend: postData.meta['alsnuff_hike_summary_ascend_meta'] || -1
        });
    }, [ postData, setAttributes ]); // 依赖postData和setAttributes

    const determineData = (value) => {
        // 只更新hikeId,其他属性交给useEffect处理
        setAttributes({ hikeId: value });
    };

    return (
        <div {...useBlockProps()}>
            <fieldset>
                <legend>Hike ID</legend>
                <TextControl
                    value={ hikeId }
                    onChange={ determineData }
                />
            </fieldset>

            <div className="card"> {/* 修正为React规范的className */}
                <footer className="card-footer">
                    <a href="#" className="card-footer-item">Distanz: { distance !== -1 ? (Math.floor(distance / 100) / 10) + 'km' : '-' }</a>
                    <a href="#" className="card-footer-item">Dauer: { duration !== -1 ? duration + 'h' : '-' }</a>
                    <a href="#" className="card-footer-item">Aufstieg: { ascend !== -1 ? ascend + 'm' : '-' }</a>
                </footer>
            </div>
        </div>
    );
};

export default HikeSummaryData;

额外优化:把JSX里的class改成className,符合React语法规范,避免潜在的渲染问题。

内容的提问来源于stack exchange,提问作者Papa Mufflon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 20:32:43