TypeError: Cannot read property 'getPosts' of undefined - useQuery hook, react Functional Components - reactjs

I did try searching for the same question but all of those were of either angular or unrelated,
I am trying to make a Social app using MongoDB, Express, React, Node, Graphql with Apollo, I am following a video from freecodecamp : Link to the video
In that video everything worked fine but in his deployed version he is having the same error as mine
react_devtools_backend.js:2450 TypeError:
Cannot read property 'getPosts' of undefined
at ae (Home.js:14)
at Jo (react-dom.production.min.js:3274)
link to the deployed app
My Code: I am dropping a link to my github repo containing the whole project : Link to github
repo
Stack Overflow was throwing too many indentation issues so i have linked my github above as there
is too much of code
I'm using semantic-ui for styling
I'm using graphql the fetch posts from MongoDB
Apollo Client for rendering data
This is the error I am getting in the Home.js:
Screen Shot of the error:

Make it simpler to debug, instead:
const {
loading,
data: { getPosts: posts }
} = useQuery(FETCH_POSTS_QUERY);
do:
const { data, loading, error } = useQuery(FETCH_POSTS_QUERY);
if(data) {
console.log(data);
const { getPosts: posts } = data;
}
if(error) {
console.log(error);
return "error"; // blocks rendering
}
this works but not when data is there and not always
"not when data", "not always"??? weird ... 'posts' can be defined only if data exists ... accessing it when undefined will fail, always ... you must check 'data'
You can/should render items (posts) ONLY when:
!loading
AND
data != undefined - if(data) or (data && in JSX
{loading && <h1>Loading posts..</h1>}
{data && (
<Transition.Group>
{posts &&
posts.map((post) => (
<Grid.Column key={post.id} style={{ marginBottom: 20 }}>
<PostCard post={post} />
</Grid.Column>
))}
</Transition.Group>
)}

use this code like this
const { loading, data: { posts } = {} } = useQuery(FETCH_POSTS_QUERY);

You need to define the query operation like:
export const FETCH_POSTS_QUERY = gql`
query GetPosts {
getPosts {
// fields
}
}
`
Alternatively, you can make use of alias to easily reference them.
export const FETCH_POSTS_QUERY = gql`
query GetPosts {
posts: getPosts {
// fields
}
}
`
const {
loading,
data: { posts } // uses alias directly. no need to rename
} = useQuery(FETCH_POSTS_QUERY);

const { loading, data: { getPosts: posts } = {} } = useQuery(FETCH_POSTS_QUERY)
This should solve the problem

THIS WILL WORK
write data.getPosts inside the grid
const { loading ,data , error } = useQuery(FETCH_POSTS_QUERY);
if (error) return Error! ${error.message};
{loading ? (<h1>Loading posts...</h1>)
: (data.getPosts &&
data.getPosts.map((post) => (
<Grid.Column key={post.id} style= {{ marginBottom: 20}}>
<PostCard post={post} />
</Grid.Column>

Related

movie-trailer npm isn't working properly in my netflix clone project

I've made a netflix clone using React.js, firebase, and have used TMDB api for movie database.
I've also used react-youtube and movie-trailer npm.
So it has this feature that every time I click on any movie poster, it's trailer must be played.
But for most of the movies, trailer doesn't shows up.
This is the error that I face -
movie-trailer: No TMDB Movie found with the current search terms, try searching https://www.themoviedb.org/search?query=Luis%20Miguel%3A%20The%20Series
TypeError: Failed to construct 'URL': Invalid URL
at Row.js:37
'This is the screenshot of errors I am facing on clicking maximum of movies'
I'm sharing the link of my github repo and deployed website as well for reference -
github - https://github.com/IshitaSharma3101/netflix-clone
website - https://netflix-clone-afb8b.web.app/
Row component code-
import React, { useState, useEffect } from "react";
import YouTube from "react-youtube";
import axios from "./axios";
import "./Row.css";
import movieTrailer from "movie-trailer"
const base_url = "https://image.tmdb.org/t/p/original/";
function Row({ title, fetchURL, isLargeRow }) {
const [movies, setMovies] = useState([]);
const [trailerURL, setTrailerURL] = useState("");
useEffect(() => {
async function fetchData() {
const request = await axios.get(fetchURL);
console.log(request.data.results);
setMovies(request.data.results);
return request;
}
fetchData();
}, [fetchURL]);
const opts = {
height: "390",
width: "100%",
playerVars: {
autoplay: 1,
},
};
const handleClick = (movie) => {
if (trailerURL) {
setTrailerURL("");
} else {
movieTrailer(movie?.name || movie?.title || movie?.original_title || "")
.then((url) => {
const urlParams = new URLSearchParams(new URL(url).search);
setTrailerURL(urlParams.get("v"));
})
.catch((error) => console.log(error));
}
};
return (
<div className='row'>
<h2>{title}</h2>
<div className='row__posters'>
{movies.map((movie) => (
<img
key={movie.id}
onClick={() => handleClick(movie)}
className={`row__poster ${isLargeRow && "row__posterLarge"}`}
src={`${base_url}${
isLargeRow ? movie.poster_path : movie.backdrop_path
}`}
alt={movie.name}
/>
))}
</div>
{trailerURL && <YouTube videoId={trailerURL} opts={opts} />}
</div>
);
}
export default Row;
I'm sure you are following the Clever Qazi tutorial as I'm doing. I think there is basically no solution for this problem. I also try to get the trailer of the movies by the ID that TMDB gives for every film but this method definitely doesn't work for mine. My conclusion is that movie-trailer is not working for certain kind of film or series...
You can prove yourself my conlclusion by typing on a terminal npx movie-trailer Cobra Kai
which is the command that allow you to use this package. Cobra Kai is a well know series but this "tool" doesn't find any trailer for it.
Use this instead.
movieTrailer(null ,{ tmdbId: movie.id })
.then((url)=>{
console.log("url is "+url);
const urlParams=new URLSearchParams(new URL(url).search);
console.log("urlParamsn"+urlParams);
setTrailerUrl(urlParams.get("v"));
})
.catch((error)=> console.log(error));
}
}
With this you can search for the movie with the tmdb id.
This error is coming becouse TMDB has not added ids for some videos if you want to play all video you just need need to change the genres of the Netflix Original Video from the path in request.js folder where you wrote your path becouse Netflix originals Videos has not linked with ids on TMDB.

Graphql subscriptions or pollInterval ? Differences in different cases?

I'm currently watching a course using MERNG stack, and it's basically an app where you post stuff, and something I was trying to achieve by myself was to get posts in real time to all users, so, my first thought was, ok, let's use graphql subscriptions, and in react using apollo/client i made this code to get new posts in real time
import React, { useContext } from "react";
import { useQuery, useSubscription, gql } from "#apollo/client";
import { Grid } from "semantic-ui-react";
import { AuthContext } from "../context/auth";
import PostCard from "../components/PostCard";
import PostForm from "../components/PostForm";
import { FETCH_POSTS_QUERY } from "../util/graphql";
const Home = () => {
const { user } = useContext(AuthContext);
const { loading, data: { getPosts: posts } = {} } = useQuery(
FETCH_POSTS_QUERY,
// {
// pollInterval: 500
// }
);
const { data: { newPost: post } = {} } = useSubscription(POSTS_REAL_TIME);
return (
<Grid columns={3}>
<Grid.Row className="page-title">
<Grid.Column>
<h1>Recent Posts</h1>
</Grid.Column>
</Grid.Row>
<Grid.Row>
{user && (
<Grid.Column>
<PostForm />
</Grid.Column>
)}
{loading ? (
<h1>Loading Posts...</h1>
) : (
posts &&
posts.map(post => {
return (
<Grid.Column key={post.id} style={{ marginBottom: "20px" }}>
<PostCard post={post} />
</Grid.Column>
);
})
)}
</Grid.Row>
</Grid>
);
};
const POSTS_REAL_TIME = gql`
subscription {
newPost {
id
body
createdAt
username
likes {
username
}
likeCount
comments {
id
username
createdAt
}
commentCount
}
}
`;
export default Home;
And i was like, ok, but... i couldn't show them in the page because i didn't know how to push that object into my array of posts that comes from my useQuery at the beginning
so i look how to stay the client updated with subscriptions, and i found a post where it shows the documentation of graphql, saying that, you shouldn't update your client using subscriptions, instead, use
pollInterval
const { loading, data: { getPosts: posts } = {} } = useQuery(
FETCH_POSTS_QUERY,
{
pollInterval: 500
}
);
So, that literally means that, i spent 2 hours trying a weird code, while, with only one line of code i can do that, so, does pollInterval replace subscriptions? how should i use subscriptions ? if i use pollInterval to keep everyone updated, is that bad for performance or something ?
Thank you for your time comunnity !
I assume the issue is not that your subscription wasn't working, but you wanted to keep the old data in the view and the new post coming in. What you need to do is keep the old data in React state or using apollo state/cache. So, rather than update the view with the new post, you update the state with the latest post, forcing a rerender of your component.
I am not an expert but I think polling is not the right way to get that done, beacuse you will continuously try to refresh the data and you will be wasting resources from your server. I would use subscriptions(Apollo Server, Apollo Client(react)), or something like socket.io, both use websockets under the hood so it doesn't make much difference.

URQL + React "typeError: Cannot read property '_react' of undefined"

I'm currently working through a urql+react tutorial found here while also adding graphQL API calls to my own application.
In the tutorial the following code is provided to send a query to the server and render components based on the result
const FEED_QUERY = gql`
{
feed {
links {
id
createdAt
url
description
}
}
}
`
const LinkList = () => {
const [result] = useQuery({ query: FEED_QUERY })
const { data, fetching, error } = result
if (fetching) return <div>Fetching</div>
if (error) return <div>Error</div>
const linksToRender = data.feed.links
return (
<div>
{linksToRender.map(link => <Link key={link.id} link={link} />)}
</div>
)
}
this code runs correctly when I implemented the tutorial myself but when I try to add this exact code to my own application I get the following error(s)
I have triple checked to make sure all the necessary urql and graphql dependencies are all installed in my application so I'm not sure what could be causing this issue.

React Apollo Query based on a condition

I'm currently building an app (hybrid mobile app) to show a list of records (places). Following is my requirement,
1) If the app is online, get the details from the server.
2) If the app is offline, get the details from the local storage.
I can get each condition working by its own. However (I'm fairly new to react and apollo-react), I'm not sure how to add a condition to the query.
below is an example of my query on getting the data from the server (I have this part working)
const client = new ApolloCient({
uri: "/graphql"
});
const PLACES_LIST = gql`
{
places {
id
title
}
}
`;
class PlacesList extends React.Component {
render() {
return (
<ApolloProvider client={client}>
<Query query={PLACES_LIST}>
{({ loading, data }) => {
if (loading) return "Loading....";
const { places } = data;
return places.map(place => (
<PlaceDetail
key={place.id}
place={place}
></PlaceDetail>
));
}}
</Query>
</ApolloProvider>
);
}
}
pseudocode for this I'm thinking would be,
if (online) {
# run apollo client
} else {
# read from the local storage
}
Can anyone point me in the correct direction. TIA.
Also, I'm using a latest version of react and I have the flexibility of using react hooks if that required.
const client = new ApolloCient({
uri: "/graphql"
});
const PLACES_LIST = gql`
{
places {
id
title
}
}
`;
class PlacesList extends React.Component {
render() {
return (
<ApolloProvider client={client}>
<Query query={PLACES_LIST}>
{({ loading, data, error }) => {
// There is also an error parameter from the hook
if (loading) return "Loading....";
// Here You can decide if its a connection error or smt other.
// I would recoment the fetchPolicy="network-only" prop for your <Query> in this case
if(error) {
return localstorage.getItem("Smt");
} else {
const { places } = data;
return places.map(place => (
<PlaceDetail
key={place.id}
place={place}
></PlaceDetail>
));
}
}}
</Query>
</ApolloProvider>
);
}
}
Maybe you can try to check for network connection using the navigator interface. I am not sure if navigator.onLine is available in hybrid mobile apps, but it would be easy to check.
You could do something like:
render(){
const isOnline = navigator.onLine
return (
<div>
{isOnline ? (
<ApolloProvider client={client}></ApolloProvider>
) : (
<LocalStorageComponent />
)}
</div>
);
}

How to use getquery with amplify <Connect/> component in React

I have been trying to use the together with a getquery in react but I can't get it to work. Below is the code I put together
const input = {
id: this.props.Id
};
return (
<div>
<Connect
query={graphqlOperation(getRecords, input)}
subscription={graphqlOperation(onCreateRecords)}
onSubscriptionMsg={onNewRecord}
>
{({data, loading, error}) => {
if (loading) return "Loading"
if (error) return "Error"
const ListRecord = data.getRecords
console.log('ListRecord', ListRecord)
//console.log returns undefined
return <div>...
</div>
}}
</Connect>
</div>
Deos anyone know what I'm doing wrong? Thanks!
It's hard to say based on what you've posted alone. Is there any additional information in the 'data' object?
Also, Have you tried doing:
query={graphqlOperation(getRecords, {input})}

Resources