CJY0208 / react-activation

Hack <KeepAlive /> for React
https://www.npmjs.com/package/react-activation
MIT License
1.78k stars 140 forks source link

react 16.14.0 报错Invalid hook call. Hooks can only be called inside of the body of a function component. #301

Closed xiaomengheiheihei closed 8 months ago

xiaomengheiheihei commented 9 months ago

详细报错信息:Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

我排查了一下项目中react和react-dom版本都是16.14.0,且仅有一个,不知道为什么会报这个错。

如果我降级react到16.4.0就没有问题了。

看了下报错应该是在这里,renderContent({ idPrefix, helpers: useScopeContext(), props })

xiaomengheiheihei commented 9 months ago

看起来是我这个导入的包装函数的问题

export function asyncComponent(importComponent, onEnter = () => {}) {
  class AsyncComponent extends Component {
    constructor(props) {
      super(props);
      this.state = {
        component: null,
        stateChangeCount: 0,
      };
      if(isInClient4()){
        moment.locale('zh-cn')
        this.pageStore = createPageSelfStore();
      }
    }

    async componentDidMount() {
      try {
        const { location } = this.props;
        const { pathname } = location;
        armsTrace.traceLogCustom({ p1: 11 });
        AddSelfAdpationClassName(pathname);
        sendPV();
      } catch (err) {}
      const { default: component } = await importComponent();
      this.setState({
        component: component,
      });
      onEnter();
    }

    componentWillUnmount() {
      try {
        sendLeave();
      } catch (err) {}
    }

    render() {
      const C = this.state.component;
      if (isInClient4()) {
        // 不缓存页面白名单
        const NO_CACHE_LIST = [
          '/collaborationPlatform/varietyReportList',
          '/drugTestManagement/varietyReportInfo',
          '/drugTestManagement/varietyReportList',
        ];
        const isNoCache = () => {
          if (NO_CACHE_LIST.find(i => i === this.props.location.pathname)) {
            return [false, true]
          } else {
            return true;
          }
        }
        return C ? (
        <KeepAlive when={isNoCache} name={this.props.location.pathname}>
          <ReduxProvider store={this.pageStore}>
            <C {...this.props} />
          </ReduxProvider>
        </KeepAlive>) : null;
      } else {
        return C ? <C {...this.props} /> : null;
      }
    }
  }

  return AsyncComponent;
}

// 会用这个包装函数来引入页面组件
const AsyncStoreScanList = asyncComponent(() =>
  import('./xx/xxxxxxx')
)
// 在通过路由包装组件引入路由
<Switch>
      <AppliedRoute
        path="/wes/wesservice"
        exact
        component={AsyncWesService}
      />
</Switch>
// 路由组件
export class AppliedRoute extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    const { path, exact } = this.props;
    const rest = this.props;
    console.log(rest, 23232323)
   // rest中component就是被包装过的页面组件,应该是个函数
    return (
      <Route {...rest} />
    );
  }
}
CJY0208 commented 8 months ago

OK,先关了