Abhilash D K Abhilash D K - 17 days ago 8
React JSX Question

componentDidMount not setting state or re-rendering

I have the below code:

import React from "react";
import * as AuthorApi from "../../../api/authorApi";

export default class Authors extends React.Component {
state = {
authors: []
};
constructor(props) {
super(props);
};

componentDidMount() {
this.setState({ authors: AuthorApi.getAllAuthors() });
}
render() {
return <div>
<h2>Authors</h2>
<table className="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{console.log("Inside: " + this.state.authors.length)}
{this.state.authors.map((author) => {
<tr key={author.id}>
<td><a href={"/#authors/" + author.id}>{author.id}</a></td>
<td>{author.firstName} {author.lastName}</td>
</tr>
}, this)}
</tbody>
</table>
</div>;
}
}


Here I am setting state in componentDidMount() method by calling an api. The console.log in render actually give array length as 3. But nothing is displayed.

AuthorApi.js

//This file is mocking a web API by hitting hard coded data.
var authors = require('./authorData').authors;
var _ = require('lodash');

//This would be performed on the server in a real app. Just stubbing in.
var _generateId = function(author) {
return author.firstName.toLowerCase() + '-' + author.lastName.toLowerCase();
};

var _clone = function(item) {
return JSON.parse(JSON.stringify(item)); //return cloned copy so that the item is passed by value instead of by reference
};

var AuthorApi = {
getAllAuthors: function () {
console.log("Inside getAll");
console.log("Authors length is : " + authors.length);
return _clone(authors);
},

getAuthorById: function(id) {
var author = _.find(authors, {id: id});
return _clone(author);
},

saveAuthor: function(author) {
//pretend an ajax call to web api is made here
console.log('Pretend this just saved the author to the DB via AJAX call...');

if (author.id) {
var existingAuthorIndex = _.indexOf(authors, _.find(authors, {id: author.id}));
authors.splice(existingAuthorIndex, 1, author);
} else {
//Just simulating creation here.
//The server would generate ids for new authors in a real app.
//Cloning so copy returned is passed by value rather than by reference.
author.id = _generateId(author);
authors.push(_clone(author));
}

return author;
},

deleteAuthor: function(id) {
console.log('Pretend this just deleted the author from the DB via an AJAX call...');
_.remove(authors, { id: id});
}
};

module.exports = AuthorApi;


Please let me know what am I doing wrong.

Answer

Try adding a return inside your map.

this.state.authors.map((author) => { 
                        return (<tr key={author.id}>
                            <td><a href={"/#authors/" + author.id}>{author.id}</a></td>
                            <td>{author.firstName} {author.lastName}</td>
                        </tr>)
                    }, this)}