jennawest
jennawest

Reputation: 1

React.js parent component do not render child components correctly

I'm new in ReactJS, but already got some problem I cannot resolve...

I have React component called Tree. This component must receive array of some data. Every element in this array must be rendered as a special child component called Department.

At the beginning, Tree has state {departments: []}, so, tree must be empty and it is. But then I change Tree's state, I set new array at departments, I see no child elements.

And the point is, that tree's state really updates, and function "render" is really called, and when I run thru departments, I get the right number of iterations in my cycle (checked with console.log). But still no child element appears.

My code works, I tried to render tree component with fixed departments and set this state in the constructor as initial state. Tree and child components worked fine.

So, I cannot imagine, what might be wrong.

Here is my code, my class Tree

class Tree extends React.Component {

    constructor(props) {
        super(props)
        this.state = {
            departments: []
        }
        this.componentDidMount = this.componentDidMount.bind(this);
    }

    componentDidMount() {
       var xhr = new XMLHttpRequest();
       xhr.open('GET', startAdress + '/tutors' + '/getAll', true);
       xhr.send();
       var tree = this;
       xhr.onreadystatechange = function() {
           if (xhr.readyState != 4) return;
           if (xhr.status != 200) {
               alert(xhr.status + ': ' + xhr.statusText);
           } else {
               var newDepts = JSON.parse(xhr.responseText);
               if (Array.isArray(newDepts.content)) {
                   tree.setState({
                       departments: newDepts.content
                   });
               }
           }
       };
   }

   render() {
       var a = this;
       console.log(JSON.stringify(this.state.departments));
       console.log(this.state.departments.length);
       return ( <div className={"Tree"}>
           {
               this.state.departments.forEach(function (department) {
                   console.log("creating branches");
                   return (
                       <Department key={department.name} department={department} />
                   );}
               ) }
           </div> )
   }
}

And here is my child component Department. It uses another component, called TreeLine, but I think it is not necessary to put it here.

class Department extends React.Component {

    constructor(props) {
        super(props)
        this.state = {
        }
    }

    render() {
        console.log("department " + JSON.stringify(this.props.department));
        return (
            <div className={'Department'}>
                <TreeLine key={this.props.department.name } classNamePostfix={"Dep"}
                item={this.props.department} />
                {this.props.department.items.forEach(function (item) {
                             return (
                                 <TreeLine key={item.name} classNamePostfix={"Item"}  item={item} />
                            )})
                 }
            </div>
        );
    }
}

Thanks in advance!

Upvotes: 0

Views: 287

Answers (1)

cfraser
cfraser

Reputation: 961

Instead of .forEach() you should be using .map().

forEach goes through every element of the array and does something with it, but nothing is returned by forEach, even if the callback returns something. On the other hand, map creates a new array with what is being returned in the callback function as an element in that new array.

const a = [1,2,3].forEach((i) => {return <span>{i}</span>})
// a = undefined
const b = [1,2,3].map((i) => {return <span>{i}</span>})
// b = [<span>1</span>, <span>2</span>, <span>3</span>]

Upvotes: 1

Related Questions