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
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);
}
I would move the logic of your get request into componentWillMount. The React error is telling you that the promise can only be called in a "Mounting component". Then you can call setState. Then in your render you can conditionally render based on the state variable.
{this.state.navList.length &&
<div>
<Header />
<SideBar navlist={this.state.navlist}/>
<HomeContent />
</div>}
You can also render a different loading component while you wait for the data to return.
You will try this
fetch(url)
.then((response) => {
let jsonData=response.json();
this.setState({data:jsonData})
})
.catch((error) => {
console.log("error---",error);
})
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"));
You have a setState
in your componentDidMount
. That creates a loop where your component will keep mounting itself forever (since setState
eventually leads to componentDidMount
being called), which is why React prevents it. The data you get through getJSON
should only update the state, not be passed on to one of React's rendering phases. When the state is updated, then your component should re-render automatically. Most of the logic you have in componentDidMount
should be in your render
function, formatting the data so it can then be used by the return
command below.
seems like the issue was separating the code properly in different files. I had index
, App
with componentDidMount()
all in one which was not working.
so i have done
index
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'));
App
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;
and the individual files... header
etc will have componentDidMount()
which now works