acess specific field graphql react - javascript

My code looks like this:
interface MutationProps {
username: string;
Mutation: any;
}
export const UseCustomMutation: React.FC<MutationProps> | any = (username: any, Mutation: DocumentNode ) => {
const [functionForDoingAction, { data, loading, error }] = useMutation(
Mutation,
{
variables: {
username,
},
}
);
useEffect(() => {
// fn trigger for change data
functionForDoingAction({
variables: {
username: username,
},
});
console.log(JSON.stringify(data));
console.log(JSON.stringify(error, null, 2));
}, []);
if (loading) return "loading...";
if (error) return `Submission error! ${error.message}`;
return data;
};
export const DisplayUser = () => {
const GET_USER = gql`
mutation GetUser($username: String!) {
getUser(username: $username) {
pfp
username
password
age
CurrentLive
ismod
description
fullname
}
}
`;
const { username }: { username: any } = useParams();
const MyData = UseCustomMutation(username, GET_USER);
console.log(JSON.stringify(MyData));
I wanna a access MyData.pfp but it gives me this error:
TypeError: Cannot read property 'pfp' of undefined
if it matters when i go on e.g. localhost:3000/user/dakepake variable MyData looks like this:
UserProfile.tsx:39 {"getUser":{"pfp":""https://i.pinimg.com/564x/65/25/a0/6525a08f1df98a2e3a545fe2ace4be47.jpg"","username":""dakepake"","password":""mohikanac10"","age":14,"CurrentLive":"""","ismod":false,"description":""this user dont have a bio yet"","fullname":""damjan alimpic"","__typename":"GetUserResponse"}}
How can I fix this?

i fixed this on my own , i just replaced MyData.pfp whit MyData.getUser.pfp and now its working

Related

I'm having problem figuring why login is working sometimes but sometimes not with Graph and Firebase

So, I have built this way of auth with firebase and graphql using mongo database, the problem is that everything is working, instead trying to login, its the same way of register but sometimes the method works and some times I get apollo client error, which I don't know why.
Here is my code to auth with Firebase and then check if the user exits and call the method and then the oposite.
import { FirebaseAuth } from "../config/Firebase";
import { GoogleAuthProvider, signInWithPopup } from "firebase/auth";
import { Notifier } from "../utils";
import { USER_AUTH_ERROR } from "../config/Responders";
const Google = async (Register, Login, dispatch) => {
var Provider = new GoogleAuthProvider();
const data = await signInWithPopup(FirebaseAuth, Provider);
try {
if (data) {
const user = data.user;
const creationTime = user.metadata.creationTime;
const lastSignInTime = user.metadata.lastSignInTime;
if (creationTime === lastSignInTime) {
const name = user.displayName.split(" ");
const firstName = name[0] || "";
const lastName = name[1] || "";
const config = {
variables: {
createUserInput: {
Name: firstName,
Surname: lastName,
Email: user.email,
Avatar: user.photoURL || null,
Uid: user.uid,
},
},
};
Register(config);
}
else {
const config = {
variables: {
uid: user.uid,
},
};
Login(config);
}
}
else Notifier(dispatch, USER_AUTH_ERROR, `error`);
} catch (error) {
Notifier(dispatch, USER_AUTH_ERROR, `error`);
}
};
export
default Google;
While here is the place where I manage the functions:
const [Register, { data: registerData }] = useMutation(REGISTER);
const [Login, { data: loginData }] = useLazyQuery(AUTH);
const Auther = () => Google(Register, Login, dispatch);
useEffect(() => {
if (!account.Auth) {
if (registerData?.hasOwnProperty("UserRegister")) {
dispatch(Authenticate(registerData.UserRegister));
}
}
}, [registerData]);
useEffect(() => {
if (!account.Auth) {
if (loginData?.hasOwnProperty("UserAuth")) {
dispatch(Authenticate(loginData.UserAuth));
}
}
}, [loginData]);
Here is the error I get:

Cannot destructure property 'name' of 'response.profileObj'

I faced with a problem while I was coding about Google sign-in line. I wrote these lines:
const Login = () => {
const navigate = useNavigate();
const responseGoogle = (response) => {
localStorage.setItem('user', JSON.stringify(response.profileObj))
const { name, googleId, imageUrl } = response.profileObj;
const doc = {
_id: response.profileObj.googleId,
_type: 'user',
userName: response.profileObj.name,
image: response.profileObj.imageUrl,
}
client.createIfNotExists(doc)
.then(() => {
navigate('/', { replace: true })
});
}
But when I am looking through console log, I see there is appearing
Uncaught TypeError: Cannot destructure property 'name' of
'response.profileObj' as it is undefined.
So what kind of solutions do you offer for me? Btw also these code should direct me to the main page after log in with my email but it also doesn't work.
You can add a null check like this.
const Login = () => {
const navigate = useNavigate();
const responseGoogle = (response) => {
localStorage.setItem("user", JSON.stringify(response.profileObj));
if (response.profileObj) {
const { name, googleId, imageUrl } = response.profileObj;
const doc = {
_id: response.profileObj.googleId,
_type: "user",
userName: response.profileObj.name,
image: response.profileObj.imageUrl,
};
client.createIfNotExists(doc).then(() => {
navigate("/", { replace: true });
});
}
};
};
Else if you provide type of the profileObj it wont throw that error
Your response.profileObj seems to be undefined
Are you sure you passed the profileObj property in the response object?

Problem sending a post graphql, nextjs react

Hello guys I have the following problem:
wherever I try to post a comment I get the following error:
ClientError: input:3: Field "post" is not defined by type CommentCreateInput.
: {"response":{"errors":[{"message":"input:3: Field \"post\" is not defined by type CommentCreateInput.\n"}],"data":null,"extensions":{"requestId":"cl3uwxntaa8r70cll4db25q72"},"status":400,"headers":{}},"request":{"query":"\n mutation CreateComment($name: String!, $email: String!, $comment: String!, $slug: String!) {\n createComment(data: {name: $name, email: $email, comment: $comment, post: {connect: {slug: $slug}}}) { id }\n }\n ","variables":{"name":"Roberto","email":"robert.rivera#outlook.com","comment":"a","slug":"react-testing"}}}
at /home/xue/Documents/Programacion/blog-nodejs/node_modules/graphql-request/dist/index.js:356:31
at step (/home/xue/Documents/Programacion/blog-nodejs/node_modules/graphql-request/dist/index.js:63:23)
at Object.next (/home/xue/Documents/Programacion/blog-nodejs/node_modules/graphql-request/dist/index.js:44:53)
at fulfilled (/home/xue/Documents/Programacion/blog-nodejs/node_modules/graphql-request/dist/index.js:35:58)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
response: {
}
API resolved without sending a response for /api/comments, this may result in stalled requests.
this is my code so far:
pages/api/comments.js
import { GraphQLClient, gql } from 'graphql-request';
const graphqlAPI = process.env.NEXT_PUBLIC_GRAPHCMS_ENDPOINT
const graphcmsToken = process.env.XUE_TOKEN
// export a default function for API route to work
export default async function asynchandler(req, res) {
console.log({graphcmsToken})
const graphQLClient = new GraphQLClient((graphqlAPI), {
headers: {
authorization: `Bearer ${graphcmsToken}`,
},
})
const query = gql`
mutation CreateComment($name: String!, $email: String!, $comment: String!, $slug: String!) {
createComment(data: {name: $name, email: $email, comment: $comment, post: {connect: {slug: $slug}}}) { id }
}
`
try {
const result = await graphQLClient.request(query, req.body)
return res.status(200).send(result)
} catch (error) {
console.log(error)
}
}
-- this my commentform.jsx
components/commentForm.jsx
import React, { useState, useEffect } from 'react';
import { submitComment } from '../services';
const CommentsForm = ({ slug }) => {
const [error, setError] = useState(false);
const [localStorage, setLocalStorage] = useState(null);
const [showSuccessMessage, setShowSuccessMessage] = useState(false);
const [formData, setFormData] = useState({ name: null, email: null, comment: null, storeData: false });
useEffect(() => {
setLocalStorage(window.localStorage);
const initalFormData = {
name: window.localStorage.getItem('name'),
email: window.localStorage.getItem('email'),
storeData: window.localStorage.getItem('name') || window.localStorage.getItem('email'),
};
setFormData(initalFormData);
}, []);
const onInputChange = (e) => {
const { target } = e;
if (target.type === 'checkbox') {
setFormData((prevState) => ({
...prevState,
[target.name]: target.checked,
}));
} else {
setFormData((prevState) => ({
...prevState,
[target.name]: target.value,
}));
}
};
const handlePostSubmission = () => {
setError(false);
const { name, email, comment, storeData } = formData;
if (!name || !email || !comment) {
setError(true);
return;
}
const commentObj = {
name,
email,
comment,
slug,
};
if (storeData) {
window.localStorage.setItem('name', name);
window.localStorage.setItem('email', email);
} else {
window.localStorage.removeItem('name');
window.localStorage.removeItem('email');
}
submitComment(commentObj)
.then((res) => {
if (res.createComment) {
if (!storeData) {
formData.name = '';
formData.email = '';
}
formData.comment = '';
setFormData((prevState) => ({
...prevState,
...formData,
}));
setShowSuccessMessage(true);
setTimeout(() => {
setShowSuccessMessage(false);
}, 3000);
}
});
};
return (
);
};
export default CommentsForm;
I don't know how to get this working and sorry for my bad english. Let me know if you need more info
edit:
this is my schema I don't know if im missing something
import { request, gql } from 'graphql-request';
const graphqlAPI = process.env.NEXT_PUBLIC_GRAPHCMS_ENDPOINT;
export const getPosts = async () => {
const query = gql`
query MyQuery {
postsConnection {
edges {
cursor
node {
author {
bio
name
id
photo {
url
}
}
createdAt
slug
title
excerpt
featuredImage {
url
}
categories {
name
slug
}
}
}
}
}
`;
const result = await request(graphqlAPI, query);
return result.postsConnection.edges;
}
export const getRecentPosts = async () => {
const query = gql`
query getPostDetails() {
posts(
orderBy: createdAt_ASC
last: 3
) {
title
featuredImage {
url
}
createdAt
slug
}
}
`;
const result = await request(graphqlAPI, query);
return result.posts;
}
export const getSimilarPosts = async ( categories, slug ) => {
const query = gql`
query GetPostDetails($slug: String!, $categories: [String!]) {
posts(
where: { slug_not: $slug, AND: { categories_some: {slug_in: $categories} } }
last: 3
) {
title
featuredImage {
url
}
createdAt
slug
}
}
`
const result = await request(graphqlAPI, query, { categories, slug });
return result.posts
}
export const getCategories = async () => {
const query = gql`
query GetCategories {
categories {
name
slug
}
}
`
const result = await request(graphqlAPI, query)
return result.categories
}
export const getPostDetails = async (slug) => {
const query = gql`
query GetPostDetails($slug : String!) {
post(where: {slug: $slug}) {
title
excerpt
featuredImage {
url
}
author{
name
bio
photo {
url
}
}
createdAt
slug
content {
raw
}
categories {
name
slug
}
}
}
`;
const result = await request(graphqlAPI, query, { slug })
return result.post
}
export const submitComment = async (obj) => {
const result = await fetch('/api/comments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(obj),
})
return result.json()
}
I assume you are using graphcms. Go to the graphcms dashboard and set up a relationship between the Post and Comment identities.
If you check well in the Schema>Post section at the end there should be a relationship with the comment entity.
graphCMS is complaining that you are trying to assign a comment to a post; when the "Post" entity has no reference to "Comment"
The Relation in graphCMS is called a Reference. From the "Post" entity assign a reference to "Comment"

Can't get the data that stored in Redis

I'm trying to create a user after he verified the code that I send him
so first I generate the code in sendCode resolver and save it in Redis using setex
the problem is that code is set in Redis but when I try to use it in createUser resolver using get it returns null.
const sendCode: MutationResolvers["sendCode"] = async ({
input: { phoneNumber, email },
}: {
input: SendCodeInput;
}) => {
const code = generate4digitNum();
await redis.setex(phoneNumber ?? email, THREE_MINS, code);
return {};
};
const createUser: MutationResolvers["createUser"] = async ({
input: { ...userData },
}: {
input: CreateUserInput;
}) => {
const code = await redis.get(userData.phoneNumber ?? userData.email);
if (code !== userData.code) {
throw new Error(errors[0].id);
}
user = await userModel.create({ ...userData});
return {type: user.type, _id: user._id };
};
the redis.ts file that I create:
const client = redis.createClient({
host: process.env.REDIS_HOST,
password: process.env.REDIS_PASSWORD,
port: Number(process.env.REDIS_PORT),
});
client
.on("connect", function () {
console.log(`connected ${client.connected}`);
})
.on("error", function (error) {
console.log(error);
});
export const get: (key: string) => Promise<string> = promisify(client.get).bind(
client
);
export const setex: (
key: string,
seconds: number,
value: string
) => Promise<string> = promisify(client.setex).bind(client);
I will appreciate any kind of help.
Thanks in advance.

After GraphQL Query: Property 'then' does not exist on type 'void'

I was using graphql mutations like this and the .then & .catch work perfectly:
let submitForm = (
email: string,
firstName: string
) => {
setIsSubmitted(true);
if (email && (firstName)) {
const input: UpdateUserInput = {};
if (firstName) {
input.firstName = firstName;
}
updateUser({
variables: {
email: email,
input: input,
},
})
.then(({ data }: ExecutionResult<UpdateUserResponse>) => {
if (data !== null && data !== undefined) {
setIsUpdated(true);
}
})
.catch((error: { message: string }) => {
console.log('Error msg:' + error.message);
});
}
};
Now I am doing something similar here for a graphql query (fuller working version below):
let ShowUsers = () => {
const where: WhereInput = {};
if (criteria === '2') {
if (searchItem) {
where.firstName_contains = searchItem;
loadUsers({
variables: {
where: where
},
})
.then(({ data }: any) => {
if (data !== null && data !== undefined) {
}
})
}
}
}
but I keep getting an error on then that Property 'then' does not exist on type 'void'
Edit:
Without the .then, .catch, my code works correctly. Full form is something like this:
function UserSearchPage() {
const [criteria, setCriteria] = useState('');
const [searchItem, setSearchItem] = useState('');
const [loadUsers, { loading, data }] = useLazyQuery(LoadUsersQuery);
function PrintUsers({ data }: any) {
return (
<div>
{data &&
data.users.nodes &&
data.users.nodes.map((c: any, i: any) => (
<li key={i}>
Id: {c.id}, First Name: {c.firstName}, Last Name: {c.lastName},
Email: {c.email}, phoneNumber: {c.phoneNumber}
</li>
))}
</div>
);
}
let ShowUsers = () => {
const where: WhereInput = {};
if (criteria === '1') {
loadUsers({
variables: {
where: where
},
});
}
if (criteria === '2') {
if (searchItem) {
where.firstName_contains = searchItem;
loadUsers({
variables: {
where: where
},
});
}
}
};
return (
.....);
}
This is how the GraphQL query itself looks like:
interface UserFilter {
email_contains: String;
firstName_contains?: String;
lastName_contains?: String;
phoneNumber_contains?: String;
id?: Number;
}
export const LoadUsersQuery = gql`
query usersList($where: UserFilter) {
users(where: $where) {
nodes {
id
email
}
totalCount
}
}
`;
How else can I access the data properties/errors?
From the console.log, I know that this is returned:
Object
__typename: "User"
email: "first#first.com"
firstName: "First"
id: 148
lastName: "User"
phoneNumber: "+49123"
But if I try to access lets say data.users.id, why do I get undefined? How can I fix this?
As stated in other answers, it's known problem - "useLazyQuery execution function should return a promise #3499"
Instead of
loadUsers({
variables: {
where: where
},
})
.then(({ data }: any) => {
if (data !== null && data !== undefined) {
}
})
you can use onCompleted option
const [loadUsers, { loading, data }] = useLazyQuery(LoadUsersQuery, {
onCompleted: ( data : any ) => {
if (data !== null && data !== undefined) {
// some action
}
}
});
It depends on what exactly is happening in loadUsers, but it's likely that you've forgotten to a return statement there.
If you change loadUsers to return the promise for the user's it's loading, your code should start working nicely.
If you look at the docs for useLazyQuery, it does not return a Promise like useMutation so they behave differently.
Instead of relying on a Promise, you must utilize the second parameters (loading, data) returned when invoking useLazyQuery. This is why in your edit, your code works without the .then.

Categories