在 React 中渲染动态子组件

Rendering a dynamic child component in React

我有一个菜单组件,它应该在另一个容器组件中动态加载元素。但是,永远不会呈现子元素。

App.js

import React, { Component } from 'react';
import './App.css';
import Menu from './components/navigation/Menu';
import Header from './components/navigation/Header';
import Container from './components/navigation/Container';

class App extends Component {
 render() {
    return (
      <div className="App" >
        <Header />
        <Menu OnMenuChange={(appName) => { this.setState({ currentApp: appName }) }} />
        <Container App={this.state.currentApp}/>
      </div>
    );
  }
}


export default App;

Container.js

import React from 'react';
import './container.css';
import { MyApp } from '../../apps';

class Container extends React.Component {

    render() {
        return (
            <div className="container">
                { this.props.App ? <this.props.App /> : null }
            </div>
        );
    }
}

export default Container;

当用户单击菜单选项时,它会在 app.js 级别触发 OnMenuChange,从而更新 Container 组件。然后将 "MyApp" 元素放入容器 div...

但是在 MyApp 组件中从未调用构造函数和渲染方法。

更新 我将菜单项列表移动到 App.js 文件中:

let navGroups = [
  {
    links: [
      {
        key: "myApp",
        name: "My App",
        type: MyApp,
      }
    ]
  }
];

然后将该列表传递到菜单中,菜单现在传递 'type' 而不是名称。这样效果更好,因为名称现在可以包含空格。

我认为问题可能是您的 state 对象在第一次渲染发生时未定义,然后阻止对其进行任何更新。我可能只是将它设置为一个空对象来初始化它。

class MyComponent extends Component {
  state = {
    App: null
  }
}

示例: https://jsfiddle.net/614ykpgg/9/

让我们考虑一下这段 JSX 转换成什么:

<this.props.App />

React.createElement(this.props.App, null)

...现在回顾一下 React.createElement 的作用。来自 the docs:

createElement()

React.createElement(
  type,
  [props],
  [...children]
)

Create and return a new React element of the given type. The type argument can be either a tag name string (such as 'div' or 'span'), or a React component type (a class or a function).

看来,你代码中的this.props.App是一个字符串。无论该字符串是 'div' 还是 'MyFancyApp',React 都假定它是 HTML 标签的名称(因为它怎么能做其他事情呢?)。

如果你希望 React 将 this.props.App 视为一个组件,this.props.App 的值必须是一个实际的组件 class 或函数——而不是名称为 a 的字符串零件。您可以更改 Menu 组件以将组件而不是字符串传递给 OnMenuChange,或者您可以像这样对 App 组件进行更改:

import PeopleApp from './PeopleApp';
import PlacesApp from './PlacesApp';

const APPS_BY_NAME = { PeopleApp, PlacesApp };

class App extends Component {
 render() {
    return (
      // ...
      <Container App={APPS_BY_NAME[this.state.currentApp]}/>
      // ...
    );
  }
}