8
votes

I found the error but someone far smarter than me has to explain why, as everything I have read has told me NOT to do it this way, see below response from me .....

I am working with react-hot-loader as well. And when I make changes and the page reloads, I receive no error. However, when I manually refresh the page I am receiving error in title above.

Simple JSON data:

const companyBlog = [
{
    blogTitle: "Company Blog",
    blogLinkTo: "companyBlog",
    blogTagLine: 'If you have any questions, contact us',
    blogPosts: [
        {
            createDate: "2015-02-10T10:50:42.389Z",
            linkTo: "blogPost1Link",
            title: "This is the title to Blog Post 1",
            content: "<p>This is the content to Blog Post 1</p>",
            author: "John Smith",
            categories: [1, 3]
        },
        {
            createDate: "2015-07-05T10:50:42.389Z",
            linkTo: "blogPost2Link",
            title: "This is the title to Blog Post 2",
            content: "<p>This is the content to Blog Post 2</p>",
            author: "Jane Doe",
            categories: [2, 3]
        },
        {
            createDate: "2015-04-22T10:50:42.389Z",
            linkTo: "blogPost3Link",
            title: "This is the title to Blog Post 3",
            content: "<p>This is the content to Blog Post 3</p>",
            author: "John Smith",
            categories: [1, 4]
        }
    ]
  }
];

Get Blog data:

getcompanyBlog() {
    let results = [];
    this.setState({
        blogTitle: companyBlog[0].blogTitle,
        blogLinkTo: companyBlog[0].blogLinkTo,
        blogTagLine: companyBlog[0].blogTagLine
    });

    companyBlog[0].blogPosts.map(function (post, index) {
        let dateArry = new Date(post.createDate).toString().split(' ');
        return(
            results.push(
                <li key= { index }>
                    <time dateTime={ post.createDate }>
                        <span>{ dateArry[1]}</span>
                        <strong>{ dateArry[2] }</strong>
                    </time>
                    <Link to='test'>{ post.title }</Link>
                </li>
            )
        )
    }.bind(this))
    this.setState({blogPosts: results});
}

Render results:

render() {
    return (
        <div>
            { this.state.blogPosts }
        </div>
    )
}

UPDATE: Here's my constructor:

constructor(props) {
    super(props);
    this.state = {
        blogTitle: '',
        blogLinkTo: '',
        blogTagLine: '',
        blogPosts: [{
            createDate: '',
            linkTo: '',
            title: '',
            content: '',
            author: '',
            categories: []
        }
        ]
    }
}

I have used this same exact method with the navigation menu and its sub menu items and do not receive any errors.

As a curious note, the error goes away, and the page loads properly, even on manual refresh when I remove { this.state.blogPosts } from the render method. Obviously though, I need that there.

And the error message:

Uncaught Error: Invariant Violation: Objects are not valid as a React child (found: object with keys {createDate, linkTo, title, content, author, categories}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of BlogSideBar.

I haven't a friggin clue what this error is telling me or how to correct.

2
I do not have much experience with the new 'let' keyword, but to my understanding it limits the scope of the variable. Are you sure you can push to it inside the map function? Have you tried logging the state object in the render function to inspect it using the web inspector? - TmKVU
I have used this same exact method, as example, with the navigation menu and it's sub children and do not receive this error. The let is at the beginning of this function and is totally accessible within it's entirety. - user1177440
it sucks that when you upgrade react.. that new errors like this shows up. This error never occurred in 0.13, now they are telling me I have to redesign my code, after this paradigm was integrated throughout my app? Good job fb. Now I know where most of your time goes.. - sksallaj

2 Answers

3
votes

Earlier in my explanation of this problem, and in response to a viewer's comment, I said that I have used this exact same method with my navigation method and received no problems. That is not true....

Before I started working on this blog, I read how the folks at React strongly discourage using ComponentWillMount and instead use ComponentDidMount.

In this blog example, unlike the Nav I mentioned, I used ....

componentDidMount() {
   this.getcompanyBlog()
}

And the problems starting happening. But, when I changed it to ...

componentWillMount() {
   this.getcompanyBlog()
}

The problems went away.

So which is it React gurus? Can I not use componentWillMount?

1
votes

This pattern should work better. Jeff has the right idea.

    getcompanyBlog() {
        this.setState({
            blogTitle: companyBlog[0].blogTitle,
            blogLinkTo: companyBlog[0].blogLinkTo,
            blogTagLine: companyBlog[0].blogTagLine,
                    blogPosts: companyBlog[0].blogPosts
        });
    }

    render() {
    if (this.state.blogPosts.length == 0) return null;
        let results = this.state.blogPosts.map(function (post, index) {
                let dateArry = new Date(post.createDate).toString().split(' ');
                return(
                    <li key= { index }>
                            <time dateTime={ post.createDate }>
                                    <span>{ dateArry[1]}</span>
                                    <strong>{ dateArry[2] }</strong>
                            </time>
                            <Link to='test'>{ post.title }</Link>
                    </li>
                )
        }, this)
    return (
        <ul>
            { results }
        </ul>
    )
    }