使用承诺时反应警告无法设置状态

react warning cannot set state when using promises

我正在尝试查询服务器以获取导航项列表,以便我可以在 init 上构建我的菜单。到目前为止,我已经设法在主页上创建了一个包含 3 个内容的静态页面,其中包括 header、边栏和内容。侧边栏是不同类型用户的不同菜单,因此我需要在加载时检索菜单项。

我收到的错误是

Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op

更新 4

所以我将 api 请求移至 index.js 文件并尝试添加 comment 中提到的条件。现在它只呈现 Loading... 并出现相同的错误

    import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import 'core-js/fn/promise';

import SideBar from './components/sidebar';
import Header from './components/header';
import HomeContent from './components/home';


function getJSON(url) {
  return get(url).then(JSON.parse);
}

function get(url) {
  // Return a new promise.
  return new Promise(function(resolve, reject) {
    // Do the usual XHR stuff
    var req = new XMLHttpRequest();
    req.open('GET', url);

    req.onload = function() {
      // This is called even on 404 etc
      // so check the status
      if (req.status == 200) {
        // Resolve the promise with the response text
        resolve(req.response);
      }
      else {
        // Otherwise reject with the status text
        // which will hopefully be a meaningful error
        reject(Error(req.statusText));
      }
    };

    // Handle network errors
    req.onerror = function() {
      reject(Error("Network Error"));
    };

    // Make the request
    req.send();
  });
}

class App extends Component {
    constructor(props){
        super(props);
        this.state = {
                        username: '',
                        user,
                        loading1: true ,
                        menuList : [],
                        loading2: true
        };
    }

    componentDidMount() {
        let currentComponent = this;

        getJSON('/api/user/get/user/method/user/format/json?quiet=1').then((response) => {
            //console.log(JSON.stringify(response));
            //currentComponent.state.username = response.body.recordset.record[0].name;
            //currentComponent.state.user = response.body.recordset.record[0];
            currentComponent.setState({
                username: response.body.recordset.record[0].name,
                loading1: false
            });
        }).catch(error => {
            console.log('Error', error);
        });

        getJSON('/api/user/get/user/method/menu/format/json?quiet=1').then((response) => {
            console.log(JSON.stringify(response));
            let menuData = response.body.recordset.record;
            let menuList = [];
            var i = 0;
            menuData.container.forEach(menus => {
                menus.sub_modules.forEach(submenu => {
                    menuList.push(<li className="menu" key={i}>{ submenu.title }</li>);
                    i++
                    if (submenu.menuitem.length) {
                        submenu.menuitem.forEach(menuitem => {
                            menuList.push(<li key={i}><a href={menuitem.link}>{ menuitem.title }</a></li>);
                            i++;
                        })
                    }
                })
            });
            currentComponent.setState({
                menuList: menuList,
                loading2: false
            });
        }).catch(error => {
            console.log("Failed!", error);
            $('#myModalError .modal-body').html(error);
            $('#myModalError').modal('show');
        });
    }

    componentWillUnmount() {}

    render() {
        let content = '';
        console.log(this.state);
        if(this.state.loading1 || this.state.loading2) {
            content = <div>Loading...</div>
        }else{
            content =
                <div id="wrapper" className="toggled">
                    <Header username={this.state.username}/>
                    <SideBar menuList={this.state.menuList}/>
                    <HomeContent />
                </div>

        }
        return <div>
                   {content}
               </div>
    }
};

ReactDOM.render(<App/>,  document.getElementById("app"));

这里是IE错误

sidebar.js

import React, { Component } from 'react';

let menuList = [];
class SideBar extends Component {
    constructor(props){
        super(props);
    }

    render () {
        return (
            <div id="sidebar-wrapper" className="hidden-print">
                <ul className="sidebar-nav">
                {this.props.menuList}
                </ul>
            </div>
        );
    }
}

export default SideBar;

我创建了一个jsfiddle

webpack

var HTMLWebpackPlugin = require('html-webpack-plugin');
var HTMLWebpackPluginConfig = new HTMLWebpackPlugin({
    template: __dirname + '/app/index.html',
    filename: 'index.html',
    inject: 'body'
});

const ExtractTextPlugin = require("extract-text-webpack-plugin");

const extractSass = new ExtractTextPlugin({
    filename: "[name].[contenthash].css",
    disable: process.env.NODE_ENV === "development"
});

module.exports = {
    entry : [__dirname + '/app/index.js'],
    module: {
         rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            } ,
            {
                test: /\.scss$/,
                use: [{
                    loader: "style-loader"
                }, {
                    loader: "css-loader"
                }, {
                    loader: "sass-loader",
                }]
            }
        ],
    },
    output: {
        filename: 'transformed.js',
        path: __dirname + '/docs'
    },
    plugins: [
        HTMLWebpackPluginConfig
    ]
}


{
  "name": "ccp-react",
  "version": "1.0.0",
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server",
    "build": "webpack"
  },
  "private": true,
  "dependencies": {
    "babel-helper-bindify-decorators": "^6.24.1",
    "babel-plugin-lodash": "^3.3.2",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-plugin-syntax-flow": "^6.18.0",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-decorators": "^6.24.1",
    "babel-plugin-transform-react-display-name": "^6.25.0",
    "babel-plugin-transform-react-jsx": "^6.24.1",
    "babel-polyfill": "^6.26.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-es2016": "^6.24.1",
    "babel-preset-es2017": "^6.24.1",
    "babel-preset-flow": "^6.23.0",
    "babel-preset-react-optimize": "^1.0.1",
    "babel-preset-stage-1": "^6.24.1",
    "babel-preset-stage-3": "^6.24.1",
    "bootstrap": "^3.3.7",
    "classnames": "^2.2.5",
    "commander": "^2.12.2",
    "create-react-class": "^15.6.2",
    "cross-env": "^5.1.3",
    "gulp": "^3.9.1",
    "hammerjs": "^2.0.8",
    "lodash": "^4.17.4",
    "ng": "0.0.0-rc6",
    "ng-cli": "^0.7.0",
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "react-icons-kit": "^1.0.7",
    "react-redux": "^5.0.6",
    "react-router": "^4.2.0",
    "react-router-dom": "^4.2.2",
    "react-side-bar": "^0.3.5",
    "react-sidenav": "^2.1.2",
    "redux": "^3.7.2",
    "rxjs": "^5.5.6",
    "systemjs": "^0.20.19",
    "web-animations-js": "^2.3.1",
    "zone.js": "^0.8.19"
  },
  "devDependencies": {
    "@types/jasmine": "~2.5.53",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "^6.0.95",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-react": "^6.24.1",
    "core-js": "^2.5.3",
    "css-loader": "^0.28.8",
    "extract-text-webpack-plugin": "^3.0.2",
    "html-webpack-plugin": "^2.30.1",
    "jasmine-core": "~2.6.2",
    "jasmine-spec-reporter": "~4.1.0",
    "karma": "~1.7.0",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.3.3",
    "karma-jasmine": "^1.1.1",
    "karma-jasmine-html-reporter": "^0.2.2",
    "node-sass": "^4.7.2",
    "protractor": "~5.1.2",
    "sass-loader": "^6.0.6",
    "style-loader": "^0.19.1",
    "ts-node": "~3.2.0",
    "tslint": "~5.7.0",
    "typescript": "~2.4.2",
    "webpack": "^3.10.0",
    "webpack-bundle-analyzer": "^2.8.2",
    "webpack-dev-server": "^2.9.7"
  }
}

即使使用与 fiddle 中相同的代码,setstate 问题仍然存在。 fiddle 作品

尝试检查更新前是否安装了组件:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

import SideBar from './components/sidebar';
import Header from './components/header';
import HomeContent from './components/home';

class App extends Component {
    constructor(props){
        super(props);
        this.mountCheck = false;
        this.state = { navlist: [] };
    }

    componentWillMount() {
        this.mountCheck = true;
    }
    componentWillUnmount() {
        this.mountCheck = false;
    }

    componentDidMount() {
         $.get('/api/user/get/user/method/menu/format/json')
        .done(( response ) => this.setState({ navlist: response } ));
    }

    render() {
        return (
            <div>
                <Header />
                <SideBar navlist={this.state.navlist}/>
                <HomeContent />
            </div>
        );
    }
};

ReactDOM.render(<App/>,  document.getElementById("app"));

您还可以添加 shouldComponentUpdate 以提高性能并减少渲染浪费,例如:

shouldComponentUpdate(nextProps, nextState) {
    if (this.state.navlist !== nextState.navlist) {
      return true;
    }
    return false;
  }

https://reactjs.org/docs/optimizing-performance.html

深度比较检查以获得更好的性能结果,您可以将其与 isEqual 的 lodash 一起使用:

shouldComponentUpdate(nextProps, nextState) {
        return !isEqual(this.state, nextState);
      }
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import SideBar from './components/sidebar';
import Header from './components/header';
import HomeContent from './components/home';

class App extends Component {
    constructor(props){
        super(props);
        this.state = { navlist: [] };
    }

  componentDidMount() {
         $.get('api/call')
        .then(( response ) => this.setState({ navlist: response } ));
    }

    render() {
        return (
            <div>
                <Header />
                <SideBar navlist={this.state.navlist}/>
                <HomeContent />
            </div>
        );
    }
};

ReactDOM.render(<App/>,  document.getElementById("app"));

注意:我添加了 2 秒的超时来模拟 API 调用。所以结果将在 2 秒后看到

const jsonResponse = {
  header: {
    title: "CCP",
    description: "",
    error: true,
    message:
      "Method getMenu Not Implemented in CCP\Controller\UserController",
    user: "UddinS2",
    nav: {
      container: [
        {
          title: "Users",
          link: "#",
          theme: "#007c92",
          sub_modules: [
            {
              title: "Getting Started",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "File - CM Template v6.3",
                  link: "/library/templates/FW-LB-CommsMatrix-Template-v6.3.xls"
                },
                {
                  title: "File - Request Access",
                  link: "/library/docs/Requesting_Access_to_CCP.pdf"
                },
                {
                  title: "Video - CCP Promo",
                  link: "/video_ccp.html"
                },
                {
                  title: "Video - CCP Demo",
                  link: "/video_ccp_demo.html"
                },
                {
                  title: "Video - Request Access",
                  link: "/video_request_access.html"
                },
                {
                  title: "Video Tutorials",
                  link: "/video_tutorials.php"
                }
              ]
            },
            {
              title: "General",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "DC Standard Networks",
                  link: "/api/user/dcsn/format/xml"
                },
                {
                  title: "Find Comms Matrix Flow",
                  link: "/find_comms_matrix_flow.php"
                },
                {
                  title: "Find Host",
                  link: "/find_host.php"
                },
                {
                  title: "Find IP Network",
                  link: "/find_network.php"
                },
                {
                  title: "List Comms Matrices",
                  link: "/comms_matrices.php"
                },
                {
                  title: "My Exemption Requests",
                  link: "/api/user/exemption/requests/format/xml"
                },
                {
                  title: "Request Exemption",
                  link: "/request_exemption.php"
                },
                {
                  title: "Services, Projects, ...",
                  link: "/api/user/services/format/xml"
                },
                {
                  title: "View FW Objects",
                  link: "/view_network_service_objects.php"
                },
                {
                  title: "Create Comms Matrix",
                  link: "/create_comms_matrix.php"
                },
                {
                  title: "Comms Matrix Templates",
                  link: "/api/user/commsmatrix/templates"
                },
                {
                  title: "Upload Comms Matrix",
                  link: "/upload_comms_matrix.php"
                },
                {
                  title: "Verify Policy Flow",
                  link: "/verify_policy_flow.php"
                },
                {
                  title: "View Security Policy",
                  link: "/security_zoning_policy.php"
                },
                {
                  title: "View Routing Policy",
                  link: "/routing_domain_policy.php"
                }
              ]
            },
            {
              title: "IP Management",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Adressing Types",
                  link: "/api/user/iam/addressing/types/format/xml"
                },
                {
                  title: "Cramer Ranges (Live)",
                  link: "/api/user/iam/cramer/ranges/format/xml"
                },
                {
                  title: "Cramer Spool Queue",
                  link: "/api/user/cramer/spool/queue/format/xml"
                },
                {
                  title: "Create Subnet",
                  link: "/iam_create_subnet.php"
                },
                {
                  title: "Subnet Types",
                  link: "/api/user/iam/subnet/types/format/xml"
                },
                {
                  title: "Zone Type Sizes",
                  link: "/api/user/security/zone/type/sizes/format/xml"
                },
                {
                  title: "My Network Diagrams",
                  link: "/api/user/iam/network/diagrams/format/xml"
                },
                {
                  title: "My Subnet Requests",
                  link: "/api/user/subnet/requests/format/xml"
                },
                {
                  title: "Range Assignments",
                  link: "/api/user/iam/range/assignments/format/xml"
                },
                {
                  title: "Upload Network Diagram",
                  link: "/iam_upload_diagram.php"
                }
              ]
            },
            {
              title: "Networks",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Entity Networks",
                  link: "/api/user/networks/by/entity/format/xml"
                },
                {
                  title: "Frozen Objects",
                  link: "/api/user/frozen/objects/format/xml"
                },
                {
                  title: "IPBB Metadata",
                  link: "/api/user/ipbb/metadata/format/xml"
                },
                {
                  title: "Map Routing Zones",
                  link:
                    "/api/user/routing/domains/mapping/routingzone/format/xml"
                },
                {
                  title: "NITX Trace",
                  link: "/nitx_trace.php"
                },
                {
                  title: "Routing Domains",
                  link: "/api/user/routing/domains/format/xml"
                },
                {
                  title: "Routing Domain Aliases",
                  link: "/api/user/aliases/routing/domains/format/xml"
                },
                {
                  title: "Routing Domains ACL",
                  link: "/api/user/routing/domains/acl/format/xml"
                },
                {
                  title: "Routing Exemptions",
                  link: "/api/user/routing/exemptions/format/xml"
                }
              ]
            },
            {
              title: "Reporting",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Statistics Dashboard",
                  link: "/statistics_dashboard.php"
                },
                {
                  title: "ECT Statistics",
                  link: "/api/user/connectivity/test/statistics"
                },
                {
                  title: "Exemption Requests",
                  link: "/api/user/report/exemption/requests/format/xml"
                },
                {
                  title: "Exemption Policies",
                  link: "/api/user/report/exemption/policies/format/xml"
                }
              ]
            },
            {
              title: "Security",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Firewall Network Objects",
                  link: "/firewall_network_objects.php"
                },
                {
                  title: "Firewall Service Objects",
                  link: "/firewall_service_objects.php"
                },
                {
                  title: "Local Market Networks",
                  link: "/api/user/networks/opco/format/xml"
                },
                {
                  title: "Security Exemptions",
                  link: "/api/user/exemptions/format/xml"
                },
                {
                  title: "Security Zones",
                  link: "/api/user/security/zones/format/xml"
                },
                {
                  title: "Security Zone Aliases",
                  link: "/api/user/aliases/security/zones/format/xml"
                },
                {
                  title: "Network Zone Aliases",
                  link: "/api/user/aliases/network/zones/format/xml"
                },
                {
                  title: "Map Security Zones",
                  link: "/api/user/security/zones/mapping/seczone/format/xml"
                },
                {
                  title: "Map Network Zones",
                  link: "/api/user/security/zones/mapping/netzone/format/xml"
                },
                {
                  title: "Security Zones ACL",
                  link: "/api/user/security/zones/acl/format/xml"
                }
              ]
            },
            {
              title: "Audit",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Firewall Network Objects",
                  link: "/api/user/audit/firewall/network/objects/format/xml"
                },
                {
                  title: "Firewall Service Objects",
                  link: "/api/user/audit/firewall/service/objects/format/xml"
                },
                {
                  title: "Security Zones",
                  link: "/api/user/audit/security/zones/format/xml"
                },
                {
                  title: "Security Zones ACL",
                  link: "/api/user/audit/security/zones/acl/format/xml"
                },
                {
                  title: "Security Zones Aliases",
                  link: "/api/user/audit/security/zone/aliases/format/xml"
                },
                {
                  title: "Security Zone Mappings",
                  link: "/api/user/audit/security/zone/mapping/format/xml"
                },
                {
                  title: "Network Zone Aliases",
                  link: "/api/user/audit/network/zone/aliases/format/xml"
                },
                {
                  title: "Routing Domains",
                  link: "/api/user/audit/routing/domains/format/xml"
                },
                {
                  title: "Routing Domains ACL",
                  link: "/api/user/audit/routing/domains/acl/format/xml"
                },
                {
                  title: "Routing Domain Aliases",
                  link: "/api/user/audit/routing/domain/aliases/format/xml"
                },
                {
                  title: "Routing Domain Mappings",
                  link: "/api/user/audit/routing/domain/mapping/format/xml"
                }
              ]
            }
          ]
        },
        {
          title: "Site Administration",
          link: "#",
          theme: "#007c92",
          sub_modules: [
            {
              title: "Content Management",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Business Units",
                  link: "/api/user/businessunits/format/xml"
                },
                {
                  title: "Entities",
                  link: "/api/user/entities/format/xml"
                },
                {
                  title: "Locations",
                  link: "/api/user/locations/format/xml"
                },
                {
                  title: "Markets",
                  link: "/api/user/markets/format/xml"
                },
                {
                  title: "Service Domains",
                  link: "/api/user/servicedomains/format/xml"
                }
              ]
            },
            {
              title: "Health Check",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Networks Status",
                  link: "/api/user/networks/status/format/xml"
                }
              ]
            },
            {
              title: "User Management",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Assign Group Privilges",
                  link: "/assign_group_privs.php"
                }
              ]
            },
            {
              title: "Troubleshooting",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Debug Comms Matrix",
                  link: "/debug_comms_matrix.php"
                },
                {
                  title: "Mocha Tests",
                  link: "/testrunner.php"
                }
              ]
            },
            {
              title: "Super Admin",
              link: "#",
              theme: "#007c92",
              menuitem: [
                {
                  title: "Sudo Group Access",
                  link: "/sudo_group_access.php"
                }
              ]
            }
          ]
        }
      ]
    },
    server: 1,
    version: "17.1",
    timestamp: 1514902917
  },
  body: []
};

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      navList: []
    };
  }

  componentDidMount() {
    //$.get('/api/user/get/user/method/menu/format/json')
    //.done ((response) => console.log(response));
    //.done(( response ) => this.setState({ navlist: //response } ));
    //dont have actual api hence setting state with response data mentioned in question
    setTimeout(() => {
      this.setState({
        navList: jsonResponse
      });
    }, 2000);
  }

  componentWillUnmount() {}

  render() {
    //removing header and HomeContent as definition is not there
    return (
      <div>
        <SideBar navlist={this.state.navList} />{" "}
      </div>
    );
  }
}
let SideBar = props => {
  const { navlist } = props;
  let navlistView = null;
  const getMenuItems = menuItemsArray => (
    <ul>
      {"       "}
      {menuItemsArray.map((element, index) => (
        <li key={index}>{element.title} </li>
      ))}
    </ul>
  );
  const getSubMenu = subMenuArray => (
    <div>
      {" "}
      {subMenuArray.map((element, index) => (
        
        <ul key={index}>-- - {element.title}
        { <li>
           {getMenuItems(element.menuitem)}
          </li>
       }
        </ul>
      ))}
    </div>
  );
  const getView = () => {
    let navlistView = null;
    if (navlist.header) {
      const navInfo = navlist.header.nav.container;
      navlistView = navInfo.map((navlist, index) => (
        <div key={index}>
        {navlist.title}
        <div>
        {getSubMenu(navlist.sub_modules)}
        </div>
        </div>
      ));
    }
    return navlistView;
  };

  return (
    <div id="sidebar-wrapper" className="hidden-print">
      {" "}
      {getView()}{" "}
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>

For first error
Failed! TypeError: Cannot read property 'setState' of undefined
issue : callback doesnot have correct context.


Failed! TypeError: Cannot read property 'menuList' of undefined
This is also context issue as getJson is called with new context.

我正在开发 linux os,没有 IE,所以我没有检查 IE。 我使用索引作为键,因为我没有任何唯一 ID。 请检查您可以将哪些唯一 ID 设置为键。

您的 componentDidMount 中有一个 setState。这会创建一个循环,您的组件将永远挂载它自己(因为 setState 最终会导致 componentDidMount 被调用),这就是 React 阻止它的原因。你通过 getJSON 获得的数据应该只更新状态,而不是传递给 React 的渲染阶段之一。当状态更新时,您的组件应该自动重新渲染。 componentDidMount 中的大部分逻辑应该在 render 函数中,对数据进行格式化,以便下面的 return 命令可以使用它。

你会试试这个

     fetch(url)
        .then((response) => {
               let jsonData=response.json();
               this.setState({data:jsonData})
         })
        .catch((error) => {
               console.log("error---",error);
         })

我会将您的获取请求逻辑移至 componentWillMount。 React 错误告诉您只能在 "Mounting component" 中调用 promise。然后你可以调用 setState。然后在您的渲染中,您可以根据状态变量有条件地渲染。

{this.state.navList.length &&
         <div>
            <Header />
            <SideBar navlist={this.state.navlist}/>
            <HomeContent />
        </div>}

您还可以在等待数据 return 时呈现不同的加载组件。

问题似乎是在不同文件中正确分隔代码。我将 indexAppcomponentDidMount() 合而为一,但无法正常工作。

所以我已经完成了

索引

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { BrowserRouter, Route, browserHistory } from 'react-router-dom';
import promise from 'redux-promise';

import App from './App'
import reducers from './reducers';

require("babel-core/register");
require("babel-polyfill");

const createStoreWithMiddleware = applyMiddleware(promise)(createStore);

ReactDOM.render(
        <Provider store={createStoreWithMiddleware(reducers)}>
            <BrowserRouter history={browserHistory}>
                <App/>
            </BrowserRouter>
        </Provider>
        , document.getElementById('root'));

应用程序

import React, { Component } from 'react'
import { HashRouter, Switch, Route, Link } from 'react-router-dom';
import Header from './components/header';
import Logout from './components/logout';
import SideBar from './components/sidebar';
import HomeContent from './components/home';
import Ldapuser from './components/ldapuser';
import AdminContent from './components/getting_started/admin';

const Main = () => (
    <main>
     <Switch>
       <Route exact path='/index.html' component={HomeContent}/>
       <Route exact path='/home' component={HomeContent}/>      
       <Route path='/logout' component={Logout}/>
       <Route path='/ldapuser' component={Ldapuser}/>
       <Route path='/admin/content' component={AdminContent}/>
     </Switch>
    </main>
)

class App extends Component {

    render() {
        return (
            <div>
                <Header />
                <SideBar />
                <Main />
             </div>
        );
    }
}

export default App;

和单个文件...header 等将有 componentDidMount() 现在有效