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

WordPress Gutenberg块编辑器中react-router跨块使用报错问题

核心结论

不能判定Gutenberg内所有块默认相互隔离、无法通过React组件或Context实现块间直接通信。你遇到的react-router上下文丢失报错,和Gutenberg序列化/解析层面的块隔离逻辑无关,本质是插件构建配置错误导致的Context实例不匹配。

根因说明
  • Gutenberg提到的块隔离是数据存储层面的:每个块的序列化内容独立存储、解析,不会互相污染保存到数据库的内容结构,不是React渲染树层面的硬隔离。正常同一份React运行时环境下,父块组件包裹的React Context完全可以被InnerBlocks渲染的子块组件读取,编辑器本身的块选中状态、编辑模式等全局状态就是靠React Context跨块传递的。
  • 你的报错来自依赖重复打包:@wordpress/scripts默认会把dependencies下声明的react-router-dom完整打包进每个块的构建bundle里,父块和子块的bundle各自包含一份独立的react-router-dom代码,会生成完全独立的Context对象。哪怕DOM结构上是父子嵌套,父块MemoryRouter提供的Context和子块Routes组件读取的Context根本不是同一个内存实例,自然会抛出“未在Router上下文内”的错误。
修复步骤

1. 调整构建配置,避免重复打包路由依赖

首先修改插件根目录的package.json,把react-router-dom从dependencies字段移到devDependencies,避免wp-scripts默认把它打包进每个块的产物。
在插件根目录新建webpack.config.js,继承官方默认配置,把react-router-dom设为外部依赖,打包时不打入bundle:

const defaultConfig = require('@wordpress/scripts/config/webpack.config');

module.exports = {
  ...defaultConfig,
  externals: {
    ...defaultConfig.externals,
    'react-router-dom': 'ReactRouterDOM',
  }
};

2. 注册全局共用的路由依赖

在插件负责注册块的PHP文件中,提前将react-router-dom的UMD构建文件注册为全局脚本(将UMD文件存放在你自己插件的资产目录下,注册时指向本地插件内的文件路径即可),并在注册两个自定义块时将该脚本设为依赖,保证父块、子块加载时都共用同一份react-router-dom实例,Context对象唯一。
示例PHP代码:

function my_custom_blocks_register() {
  // 注册全局共用的react-router-dom脚本
  wp_register_script(
    'react-router-dom-global',
    plugins_url( 'assets/vendor/react-router-dom.umd.min.js', __FILE__ ),
    [ 'react', 'react-dom' ],
    '6.3.0'
  );

  // 注册父块,添加全局路由脚本依赖
  register_block_type( __DIR__ . '/build/react-router-wrapper-block', [
    'editor_script_deps' => [ 'react-router-dom-global' ]
  ] );

  // 注册子块,同样添加依赖
  register_block_type( __DIR__ . '/build/react-router-single-route', [
    'editor_script_deps' => [ 'react-router-dom-global' ]
  ] );
}
add_action( 'init', 'my_custom_blocks_register' );

3. 修复现有代码的属性冲突问题

父块react-router-wrapper-block/edit.js中,你给外层div和内层路由链接容器都绑定了{...blockProps},blockProps包含块唯一ID等自定义属性,重复绑定会引发DOM属性冲突,删除内层div上的{...blockProps}即可。

可选替代方案

如果你不想手动处理依赖打包问题,也可以用Gutenberg原生能力实现块间通信:

  • 用@wordpress/data创建自定义全局状态存储,父子块通过统一的store读写状态,不依赖React Context穿透
  • 用官方原生的Block Context API,父块声明要向下传递的上下文属性,子块声明接收对应属性,是官方专门提供的父子块传值能力,稳定性更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 10:24:13