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

Gutenberg区块无法保存渲染棋盘:React无效钩子调用错误排查

解决Gutenberg区块无效钩子调用错误(Error: Minified React error #321)

错误根源

Gutenberg的save函数必须是纯函数,不允许包含React钩子(如useEffect),也不能渲染带有钩子的组件。你的save.js中直接渲染了PGNViewer组件,而该组件使用了useEffect,这违反了save函数的规则,直接触发无效钩子调用错误,同时导致区块无法生成静态HTML、无法保存。

解决方案

1. 修改save.js,仅保存原始PGN代码

save函数只返回存储PGN代码的容器,不做任何动态渲染:

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

export default function save({ attributes }) {
    const blockProps = useBlockProps.save();

    return (
        <div {...blockProps} data-pgn={attributes.pgnCode}>
            {/* 仅存储原始PGN代码,由前端脚本负责渲染棋盘 */}
        </div>
    );
}

2. 调整Edit组件,添加编辑器内实时预览

在编辑器中保留棋盘预览,让用户实时看到输入效果:

import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import './editor.scss';
import PGNViewer from './PGNViewer';

export default function Edit({attributes, setAttributes}) {
    const blockProps = useBlockProps();

    const handleChange = (val) => {
        setAttributes({ pgnCode: val });
    };

    return (
        <div {...blockProps}>
            <RichText
                className="pgn-textarea"
                tagName="p"
                placeholder={__("Enter PGN code here...", "wcbp")}
                value={attributes.pgnCode}
                onChange={handleChange}
                allowedFormats={[]}
            />
            {/* 编辑器内预览棋盘,仅当有PGN代码时渲染 */}
            {attributes.pgnCode && <PGNViewer attributes={attributes} />}
        </div>
    );
}

3. 创建前端渲染脚本(frontend.js)

在前端页面加载时,读取保存的PGN代码并调用pgnView生成棋盘:

import { pgnView } from '@mliebelt/pgn-viewer';

document.addEventListener('DOMContentLoaded', () => {
    const pgnBlocks = document.querySelectorAll('[data-pgn]');
    
    pgnBlocks.forEach((block, index) => {
        const pgnCode = block.getAttribute('data-pgn');
        if (!pgnCode) return;

        const boardId = `board-${index}-${Math.floor(Math.random() * 100000)}`;
        const boardContainer = document.createElement('div');
        boardContainer.id = boardId;
        block.appendChild(boardContainer);

        pgnView(boardId, {
            pgn: pgnCode,
            notation: 'long',
            layout: 'left',
            locale: 'pl',
            startPlay: 1,
            showResult: true,
            boardSize: '500',
            showFen: false,
            pieceStyle: 'merida'
        });
    });
});

4. 更新区块注册配置

在block.json中声明前端脚本依赖,确保脚本被正确加载:

{
  "apiVersion": 3,
  "name": "wcbp/pgn-viewer",
  "title": "PGN Chess Viewer",
  "category": "widgets",
  "icon": "chess",
  "description": "Embed a chess board from PGN notation",
  "supports": {
    "html": false
  },
  "attributes": {
    "pgnCode": {
      "type": "string",
      "default": ""
    }
  },
  "editorScript": "file:./index.js",
  "editorStyle": "file:./editor.scss",
  "style": "file:./style.scss",
  "script": "file:./frontend.js"
}

关键说明

  • Gutenberg的save函数仅负责生成静态HTML,不能包含任何副作用或React钩子。
  • 动态渲染逻辑(如调用pgnView)必须放在前端脚本中,在页面加载时执行。
  • 编辑器内的预览可以正常使用,因为Edit组件运行在React环境中,允许使用钩子。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:25:21