Reputation: 86
import React, {Component} from 'react';
import { Link } from 'react-router';
class AsideNav extends Component{
constructor(props, context) {
super(props, context);
this.state = {
navigation: ''
};
}
componentWillMount(){
console.log(this.props.data.navigation); // data from parent received
this.setState({
navigation: this.props.data.navigation.map(function(el, index){
return(
<Link key={index} className={"aside-nav__link " + (el.modifier ? ("aside-nav__link" + el.modifier) : '')} to={el.url}>{el.name}</Link>
)
})
})
}
render() {
console.log(this.state.navigation); // JSX for navigation is ready
return (
<nav className="aside-nav">
<span className="aside-nav__title" >Категории</span>
{this.state.navigation}
</nav>
);
}
}
export default AsideNav
After (seemingly) successful implementation of code it displays me an empty block and
Uncaught TypeError: Cannot read property 'navigation' of undefined at AsideNav.componentWillMount...
Upvotes: 1
Views: 3812
Reputation: 86
import React from 'react';
import {render} from 'react-dom';
import { Router, Route, browserHistory } from 'react-router';
import App from './app';
import PageDashboard from './page-templates/page-dashboard';
import PageRating from './page-templates/page-rating';
import './styles/css/style.css';
//render(<PageDashboard />, document.querySelector('.main-wrapper')); - before
render(
<Router history={browserHistory}>
//<Route path="/public/" component={App} /> - before
<Route path="/public/" component={PageDashboard} /> // - now
<Route path="/public/rating" component={PageRating} />
</Router>, document.querySelector('.main-wrapper')
);
A problem located in root file 'main.js'. I accidentally have mounted two components with common children.
Upvotes: 0
Reputation: 104459
Changes:
1. Never store the ui items
in state variable, always store data only and then generate the ui
elements dynamically.
2. Use componentWillReceiveProps
method, it will get called if you do any changes in props
values in parent component, update the state
value of child component at that time.
3. Since you just want to create the items from props
data, directly use props
, instead of storing anything.
Write it like this:
import React, {Component} from 'react';
import { Link } from 'react-router';
class AsideNav extends Component{
constructor(props, context) {
super(props, context);
this.state = { };
}
renderLinks(){
let data = this.props.data;
return data && Array.isArray(data.navigation) && data.navigation.map((el, index) => {
return(
<Link
key={index}
className={"aside-nav__link " + (el.modifier ? ("aside-nav__link" + el.modifier) : '')}
to={el.url}
>
{el.name}
</Link>
)
})
}
render() {
console.log(this.props.data)
return (
<nav className="aside-nav">
<span className="aside-nav__title" >Категории</span>
{this.renderLinks()}
</nav>
);
}
}
Upvotes: 1
Reputation: 12103
se componentWillReceiveProps(newProps) to get props second time as constructor and componentDidMount methods get executed only once. And also add check if data available or not.
import React, {Component} from 'react';
import { Link } from 'react-router';
class AsideNav extends Component{
constructor(props, context) {
super(props, context);
this.state = {
navigation: ''
};
}
componentWillReceiveProps(newProps)
{
console.log(newProps.data.navigation); // data from parent received
this.setState({
navigation: newProps.data &&newProps.data.navigation.map(function(el, index){
return(
<Link key={index} className={"aside-nav__link " + (el.modifier ? ("aside-nav__link" + el.modifier) : '')} to={el.url}>{el.name}</Link>
)
})
})
}
componentWillMount(){
console.log(this.props.data.navigation); // data from parent received
this.setState({
navigation: this.props.data && this.props.data.navigation.map(function(el, index){
return(
<Link key={index} className={"aside-nav__link " + (el.modifier ? ("aside-nav__link" + el.modifier) : '')} to={el.url}>{el.name}</Link>
)
})
})
}
render() {
console.log(this.state.navigation); // JSX for navigation is ready
return (
<nav className="aside-nav">
<span className="aside-nav__title" >Категории</span>
{this.state.navigation}
</nav>
);
}
}
export default AsideNav
Upvotes: 0