React Redux类组件继承Redux连接组件时触发Super expression TypeError
错误根因定位
这个报错和新版React-Redux兼容性、循环依赖都没有关系,核心原因是你继承的父类根本不是合法的ES类构造函数。
你在引入AutocompleteWidget时,拿到的不是自己编写的那个继承自BaseWidget的原生类组件:
- AutocompleteWidget模块中,
export default导出的是connect(mapStateToProps, mapDispatchToProps)(AutocompleteWidget)的返回值 - connect是高阶函数,返回的是经过Redux逻辑封装的React组件,这个返回值既不是ES类,也不是可被
extends使用的构造器 - 当你书写
class AssetWidget extends 导入的AutocompleteWidget时,由于父类不是合法构造函数,直接触发TypeError: Super expression must either be null or a function
适配方案(无需重写原有组件)
按照你不改动原有组件核心逻辑的要求,仅需调整AutocompleteWidget的导出结构,将原生类单独暴露供后续继承使用即可:
调整AutocompleteWidget的导出逻辑
将内部原生类做命名导出,保留原有默认导出逻辑完全不变,不影响已有的业务页面使用:
import { getAutocompleteOptions } from 'options/modules/autocomplete'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import BaseWidget from './BaseWidget'; // 原生类组件,单独命名导出供后续业务组件继承 export class RawAutocompleteWidget extends BaseWidget { onChange = e => { this.props.onChange({ target: { value: e } }); }; get options() { return ['options0', 'options1', 'options2']; } } const mapStateToProps = ({ autocomplete }) => { return { autocomplete, }; }; const mapDispatchToProps = dispatch => bindActionCreators( { getAutocompleteOptions, }, dispatch, ); // 原有默认导出逻辑保留,供页面直接引入使用 export default connect(mapStateToProps, mapDispatchToProps)(RawAutocompleteWidget);
调整AssetWidget的导入逻辑
AssetWidget继承时,导入的是未被connect包裹的原生类,而非模块默认导出的包装组件:
// 导入命名导出的原生类,而非默认导出的connect包装版本 import { RawAutocompleteWidget } from './AutocompleteWidget'; export default class AssetWidget extends RawAutocompleteWidget { get options() { return ['asset0', 'asset1', 'asset2']; } }
如果AssetWidget本身需要连接Redux获取数据,单独给AssetWidget套connect逻辑即可,和原有组件的逻辑完全解耦。
类组件迁移的注意事项
- ES类的
extends语法要求父类必须是合法的构造函数,普通对象、高阶组件、undefined作为父类都会触发当前报错 - 不要试图继承connect返回的包装组件:这个包装组件的核心作用是透传store注入的props,本身不会继承内部原组件的原型方法(比如你重写的
get options、onChange),就算不触发报错,继承得到的逻辑也完全错误 - 类组件的继承链上,所有被继承的类必须是原生可实例化的类,任何经过高阶组件包装的组件,都需要剥离出内部的原生类再做继承
内容的提问来源于stack exchange,提问作者Kyle Calica-St
相关产品推荐
相关产品推荐

