Abhilash D K
Abhilash D K

Reputation: 1309

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.

Upvotes: 1

Views: 316

Answers (1)

forgng
forgng

Reputation: 108

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)}

Upvotes: 2

Related Questions