2

我正在使用反应路由器、webpack 和动态导入为反应应用程序创建代码拆分解决方案。这个想法是将所有路由和相应的组件映射到不同的应用程序上下文并根据应用程序上下文拆分代码。当用户访问某个路由时,相关应用上下文的整个代码块正在被加载。

代码示例:

应用程序.tsx:

class App extends React.Component<Props, State> {
  render() {    
    if (this.props.data.loading || this.props.localData.loading) {
      return <Loader />
    }

    return (
      <IntlProvider locale={this.props.localData.session.locale} messages={this.state.translations}>
        <Router history={history}>
            <Route
              exact
              path={`/screens/:action?`}
              render={() => <ComponentLoader contextName={Context.Screens} componentName={'ScreenList'} />}
            />
        </Router>
      </IntlProvider>
    )
  }
}

export default withData(App)

组件加载器.tsx:

export enum Context {
  Screens = 'Screens',
  Channels = 'Channels'
}

const CONTEXT_LOADERS: { [name: string]: ComponentChunkLoader } = {
  [Context.Screens]: () => import('../../routerContexts/screens'),
  [Context.Channels]: () => import('../../routerContexts/channels'),
}

const loadedContexts: ContextsCollection = {}

class ComponentLoader extends React.PureComponent<Props, State> {

  state: State = {
    Component: null
  }

  async componentDidMount() {
    this._updateComponent(this.props)
  }

  async componentDidUpdate(prevProps: Props, prevState: State) {
    if (this.props.componentName !== prevProps.componentName || this.props.contextName !== prevProps.contextName) {
      this._updateComponent(this.props)
    }
  }

  _updateComponent = async (props: Props) => {
    let module = loadedContexts[props.contextName]
      ? loadedContexts[props.contextName]
      : await CONTEXT_LOADERS[props.contextName]()

    if (!loadedContexts[props.contextName]) loadedContexts[props.contextName] = module

    let ComponentClass = module[props.componentName]

    this.setState({
      Component: ComponentClass
    })
  }

  render() {

    if (this.state.Component !== null) {
      return <this.state.Component />
    }

    return <Loader />
  }
}

export default ComponentLoader

因此,当我切换到不同的路线时,我可以正确看到所有组件,并且代码拆分也可以正常工作。

问题是:当反应上下文中的数据更新时,ScreenList示例中的组件不会更新。当我ScreenList直接通过反应路由器时,Route一切正常。所以问题出在我ComponentLoader用于代码拆分的组件中。

任何想法可能是什么原因?

更新: Alrite,我现在发现:如果我将我的包装ComponentLoader在一个 HOC 中,该 HOC 从上下文(如)注入一些数据export default withRouter(ComponentLoader),一切正常,组件按预期重新呈现。为什么会这样?

4

0 回答 0