fabien0102 / gatsby-starter

Gatsby 2.0 starter with typescript and many cools dev tools
386 stars 99 forks source link

TypeError: Cannot read property 'children' of null #46

Closed mghazwi closed 6 years ago

mghazwi commented 6 years ago

I downloaded the starter and the blog page has this error after I generated a blog post with npm run generate "blog post"

TypeError: Cannot read property 'children' of null
React.createElement.posts.map
src/pages/blog.tsx:34
  31 | {posts.map(({ node }) => {
  32 |   const { frontmatter, timeToRead, fields: { slug }, excerpt } = node;
  33 |   const avatar = frontmatter.author.avatar.children[0] as ImageSharp;
> 34 |   const cover = frontmatter.image.children[0] as ImageSharp;
  35 | 
  36 |   const extra = (
  37 |     <Comment.Group>
View compiled
./src/pages/blog.tsx.exports.default.props
src/pages/blog.tsx:29
  26 | const pageCount = Math.ceil(props.data.posts.totalCount / 10);
  27 | 
  28 | // TODO export posts in a proper component
> 29 | const Posts = (
  30 |   <Container>
  31 |     {posts.map(({ node }) => {
  32 |       const { frontmatter, timeToRead, fields: { slug }, excerpt } = node;
mghazwi commented 6 years ago

i tried it again and got different error:

TypeError: Cannot read property 'tags' of undefined
./src/pages/blog.tsx.exports.default.props
src/pages/blog.tsx:23
  20 | }
  21 | 
  22 | export default (props: BlogProps) => {
> 23 |   const tags = props.data.tags.group;
  24 |   const posts = props.data.posts.edges;
  25 |   const { pathname } = props.location;
  26 |   const pageCount = Math.ceil(props.data.posts.totalCount / 10);
dvulanov commented 6 years ago

This code requires an image and tag for blog posts. If they are not specified in the frontmatter then errors are thrown. You should specify both and make sure the image in located local to the post.

i001962 commented 6 years ago

I too am getting this error. It seems that changing the Author ID causes the error. I wondered if it has something to do with blogs.tsx line 28 // TODO export posts in a proper component

The starter content worked as expected and I could see the blog posts. <update - don't do this> Then I created a new folder under blogs to hold the new post (index.md and the image). When I went to change author ID from 'fabien BENARD' to a new name in both the author.json and index.md the error occurs. Any thoughts? My gatsby knowledge is all of 4 tutorials. Appreciate any pointers you may have on how to fix this.

UPDATE: OK - face/palm

I see now that "npm run generate" will use plop to create a blog post (or page). So, success after updating the author.json to add a new author and image THEN after "npm run generate" adding the blog post's image to the newly created blog/ as you suggested. Worked like a charm. Hopefully someone finds this useful and you didn't put any time into looking into it.

fabien0102 commented 6 years ago

@i001962 @mghazwi Just to be sure, is it resolved for you? If yes, you can maybe add some useful tips in the README.md (I accept PR 😃 ) It's not always easy to explained how everything works, so some externals feedbacks is always a good point for me 👍

sielay commented 6 years ago

It's because an image is missing. In my fork, I added a simple check for its existence. https://github.com/sielay/sielay.com/blob/sielay.com/src/pages/blog.tsx#L26

fabien0102 commented 6 years ago

@sielay Not a bad idea! I will add this also in this starter ;)

Edit: Not really fit with this starter ^^ Every card need the cover also, I will keep this as it is for now ;)

return (
          <Card key={slug}
            fluid
            image={{
              src: cover.responsiveResolution.src,
              srcSet: cover.responsiveResolution.srcSet,
            }}
            header={frontmatter.title}
            extra={extra}
            description={description}
          />
        );
fabien0102 commented 6 years ago

@sielay BTW, you can totally remove your check, cover is unused in your project 😄

sielay commented 6 years ago

Sometimes I use sometimes no :P You know what would be awesome?

I saw recently repo that uses Proxies that returns itself helping to avoid issues with null/undefined in the chain. Can't dig it out, but would be awesome to use such approach without checks each time.

fabien0102 commented 6 years ago

We can also simply use lodash.get for this kind of issues, but I don't know what you means by "Proxies", any links/example to help me?

sielay commented 6 years ago

I meant those https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy. I will try to dig out the specific project. It works like magic method in PHP. Basically, you have an object which can carry null/undefined, but if you ask for children that don't exist it safely gives you undefined instead of crashing.

fabien0102 commented 6 years ago

Interesting! But definitively lodash.get ^^ Proxy can be nice, but a little bit overkill for this usecase on my own opinion.

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// => 3

_.get(object, ['a', '0', 'b', 'c']);
// => 3

_.get(object, 'a.b.c', 'default');
// => 'default'

https://lodash.com/docs/4.17.5#get

So in our case:

const cover = get(frontmatter, "image.children.0.responsiveResolution", {})
i001962 commented 6 years ago

@fabien0102 just submitted PR #61 for the README.md. It will be my first contribution (ever) if you find it acceptable. Noob learning.

fabien0102 commented 6 years ago

@i001962 Welcome to beautiful world of the open source 😁