I'm trying to query the server to get list of nav items so I can build my menu on init. I've so far managed to create a static page with 3 contents on the home page, which includes header, sidebar and content. The sidebar is the menu which is different for different type of users so I need to retrieve the menu items on load.
Error I receive is
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
Update 4
so i moved my api requests to index.js
file and tried to add the condition as mentioned in the comment. Now it just renders Loading...
with the same error
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"));
here is IE error
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;
I have created a 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"
}
}
setstate issue still exists even with same code as the one in the fiddle. the fiddle works
try to check if the componenet mounted before you update:
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"));
also you can add shouldComponentUpdate to improve performance and reduce wastful rendering e.g:
shouldComponentUpdate(nextProps, nextState) {
if (this.state.navlist !== nextState.navlist) {
return true;
}
return false;
}
see https://reactjs.org/docs/optimizing-performance.html
deep compare check for better performance results you can use it with isEqual
's 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"));
Note: I have added a timeout of 2 seconds to simulate API call. so results will be seen after 2 seconds
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.
I am working on linux os , dont have IE , So I haven't checked on IE. i have used index as the keys because i don't have have any unique id. Please check what unique id you can set as keys.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With