'TypeError: Cannot read properties of undefined using reactjs and graphql
I'm creating a social media using RactJS, Mongoose, GraphQL and Apollo. When I try to fetch data from DB to be displayed in the home page I get an error saying TypeError: Cannot read properties of undefined (reading 'getPosts'). I search for the solution and tried a bunch of things and nothing worked
File structre
--client
----node_modules
----public
----src
------components
--------MenuBar.js
--------PostCard.js
------pages
--------Home.js
--graphQL
----resolvers
--------comments.js
--------index.js
--------posts.js
--------users.js
----typeDefs.js
--models
----Post.js
----User.js
Home.js
import React from 'react';
import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';
import { Grid } from 'semantic-ui-react';
import PostCard from '../components/PostCard';
function Home() {
const { loading, data: { getPosts: posts } } = useQuery(FETCH_POSTS_QUERY);
return (
<Grid columns={3}>
<Grid.Row>
<h1>Recent Posts</h1>
</Grid.Row>
<Grid.Row>
{loading ? (
<h1>Loading posts..</h1>
) : (
posts && posts.map(post => (
<Grid.Column key={post.id}>
<PostCard post={post} />
</Grid.Column>
))
)}
</Grid.Row>
</Grid>
)
}
const FETCH_POSTS_QUERY = gql`
{
getPosts{
id
body
createdAt
username
likeCount
likes {
username
}
commentCount
comments{
id
username
createdAt
body
}
}
}
`;
export default Home;
posts.js
const { AuthenticationError, UserInputError } = require('apollo-server');
const Post = require('../../models/Post');
const checkAuth = require('../../util/check-auth');
module.exports = {
Query: {
async getPosts() {
try {
const posts = await Post.find().sort({ createdAt: -1 });
return posts;
} catch (err) {
throw new Error(err);
}
},
async getPost(_, { postId }) {
try {
const post = await Post.findById(postId);
if(post) {
return post;
} else {
throw new Error('Post not found')
}
} catch (err) {
throw new Error(err);
}
}
},
Mutation: {
async createPost(_, { body }, context) {
const user = checkAuth(context);
if(args.body.trim() === '') {
throw new Error('Post body must not be empty');
}
const newPost = new Post({
body,
user: user.id,
username: user.username,
createdAt: new Date().toISOString()
});
const post = await newPost.save();
context.pubsub.publish('NEW_POST', {
newPost: post
});
return post;
},
async deletePost(_, { postId }, context) {
const user = checkAuth(context);
try {
const post = await Post.findById(postId);
if(user.username === post.username) {
await post.delete();
return 'Post deleted successfully';
} else {
throw new AuthenticationError('Action not allowed');
}
} catch (err) {
throw new Error(err);
}
},
async likePost(_, { postId }, context) {
const { username } = checkAuth(context);
const post = await Post.findById(postId);
if (post) {
if (post.likes.find((like) => like.username === username)) {
// Post already likes, unlike it
post.likes = post.likes.filter((like) => like.username !== username);
} else {
// Not liked, like post
post.likes.push({
username,
createdAt: new Date().toISOString()
});
}
await post.save();
return post;
} else throw new UserInputError('Post not found');
}
},
Subscription: {
newPost: {
subscribe: (_, __, { pubsub }) => pubsub.asyncIterator('NEW_POST')
}
}
}
When I console.log(data) before implementing the data: {getPosts: posts} it runned smoothly returning an object as expected but after that the app crashed.
Solution 1:[1]
maybe try this:
const { loading, data } = useQuery(FETCH_POSTS_QUERY)
const { getPosts: posts } = {...data}
or another way is to do this:
const { loading, data: { getPosts: posts } = {} } = useQuery(FETCH_POSTS_QUERY)
Let me know if it still doesn't work leave a comment below.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
