GraphQL subscriptions - javascript

I'm having a hard time with GraphQL today. Probably encountered every single error possible.
I want to be able to subscribe to websockets in my component so I wrote some code to do this. Subscription works fine and it seems like it work, but the problem I have is how to get the updated values that come from the subscription inside my component?.
const FIELD_QUE = gql`
query fieldChanged($fieldName: String!, $projectId: Int!) {
fieldChanged(fieldName: $fieldName, projectId: $projectId) {
usersEmail
value
projectId
}
}
`;
const FIELD_MUT = gql`
mutation ChangeFieldMutation($fieldName: String!, $projectId: Int!, $value: String!, $usersEmail: String!) {
changeField(fieldName: $fieldName, projectId: $projectId, value: $value, usersEmail: $usersEmail) {
projectId
value
usersEmail
}
}
`;
const withMutation = graphql(FIELD_MUT, {
props: ({ ownProps, mutate }) => ({
changeField: ({ fieldName, value, projectId, usersEmail }) => {
mutate({
variables: { fieldName, value, projectId, usersEmail },
});
},
}),
});
const FIELD_SUB = gql`
subscription onFieldChanged($projectId: Int!){
fieldChanged(projectId: $projectId){
projectId
value
usersEmail
}
}
`;
const withSubscription = graphql(FIELD_QUE, {
name: 'fieldChanged',
options: () => ({
variables: {
projectId: 1,
fieldName: 'description',
},
}),
props: props => ({
subscribeToFieldChange: (params) => {
return props.fieldChanged.subscribeToMore({
document: FIELD_SUB,
variables: {
projectId: params.projectId,
fieldName: params.fieldName,
},
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const newValue = subscriptionData.data;
const result = { ...prev, ...newValue };
return result;
},
});
},
}),
});
All I get is this:

Related

Graphql doesn't return the data

I'm trying to find a specific data based on the id in graphql.
But it is returning null .
I have also tried the mutation. Here is also it is returning null.
What's wrong with this below code.
const { ApolloServer } = require("#apollo/server");
const { startStandaloneServer } = require("#apollo/server/standalone");
const students = [
{
name: "langesh",
roll: 131,
},
{
name: "ram",
roll: 134,
},
];
const typeDefs = `#graphql
type Student {
name: String,
roll: Int,
}
type Query {
students: [Student]
student(roll: Int) : Student
}
`;
const resolvers = {
Query: {
students: () => students,
student: (parent, roll) => {
return students.find((s) => s.roll === roll);
},
},
};
const server = new ApolloServer({ typeDefs, resolvers });
async function startServer() {
const { url } = await startStandaloneServer(server, {
listen: {
port: 8000,
},
});
console.log(`url : ${url}`);
}
startServer();
You need to destructure the args in your resolver.
Instead of:
student: (parent, roll) => {
return students.find((s) => s.roll === roll);
}
do:
student: (parent, { roll }) => {
return students.find((s) => s.roll === roll);
}

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"

acess specific field graphql react

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

Redux Thunk data is stored as a string not as an object

I want store a new group as an object into the groups entity in the store. Everything works perfectly but the new group is stored as an object not as a string. I am using Mockoon to mock an API and the data type is set to be application/json. Can someone explain to me what might be the possible cause of this behavior? I am quite new on using redux so some input would be really appreciated too.
Thank you
const dispatch = useDispatch();
const initialGroupState = {
id: null,
name: "",
description: "",
members: []
}
const [group, setGroup] = useState(initialGroupState)
const [submitted, setSubmitted] = useState(false);
const handleInputChange = event => {
const { name, value } = event.target;
setGroup({ ...group, [name]: value });
};
const saveGroup = (e) => {
e.preventDefault();
const {name, description} = group;
dispatch(createGroup(name, description))
.then(data => {
setGroup({
id: Math.floor(Math.random() * 10000),
name: data.name,
description: data.description,
});
setSubmitted(true);
})
.catch(e => {
console.log(e);
});
}
const newGroup = () => {
setSubmitted(false);
};
My reducer:
const initialState = []
function groupsReducer(groups = initialState, action) {
const { type, payload } = action;
console.log([...groups]);
switch (type) {
case CREATE_GROUP:
return [...groups, payload];
case RETRIEVE_GROUPS:
return payload;
default:
return groups;
}
};
My actions:
export const createGroup = (name, description) => async (dispatch) => {
try {
const res = await GroupDataService.create({ name, description });
dispatch({
type: CREATE_GROUP,
payload: res.data,
});
console.log(res.data)
return Promise.resolve(res.data);
} catch (err) {
console.log(err)
return Promise.reject(err);
}
};

storing persistent object in asyncStorage

I do not know if this is possible, but I am trying to store persistent data in async storage, so whenever the array data in the storage key is fetched, that persistent data is always at the top of the array. Also, persistent data cannot be deleted. below is a sample code, and I have shown only the functions for better clarity.
componentWillMount() {
this.saveData();
}
componentDidMount() {
this.getDataSync();
}
getDataSync = async () => {
try {
const list = await AsyncStorage.getItem(LIST_STORAGE_KEY);
const parsedList = JSON.parse(list);
this.setState({
isDataReady: true,
list: parsedList || []
});
console.log(parsedList, this.state.list);
} catch (e) {
Alert.alert('Failed to load list.');
}
}
saveData = () => {
const data = [
{
firstname: 'John',
lastname: 'Doe',
image: null,
email: 'john#doe.com',
key: 0,
phone: '19191919191',
},
];
this.setState(
prevState => ({
list: [data, ...prevState.list]
}),
() => this.saveItems(this.state.list)
);
}
handleDelete(item) {
if (item.key === 0) {
Alert.alert('You cannot delete this user');
} else {
this.setState(({ list }) => ({
list: list.filter(o => o.key !== item.key)
}),
() => this.saveItems(this.state.list)
);
console.log('deleted: ', item);
}
}
handleAdd() {
const { firstname, lastname, email, phone } = this.state;
const ID = uuid();
const newItemObject = {
key: ID,
firstname: firstname,
lastname: lastname,
email: email,
phone: phone,
image: null,
};
this.setState(
prevState => ({
list: [...prevState.list, newItemObject]
}),
() => this.saveItems(this.state.list)
);
}
saveItems = list => {
AsyncStorage.setItem(LIST_STORAGE_KEY, JSON.stringify(list));
};
Add another property to the objects, you don't want to be deleted. Asyncstorage is persistent by default.
{
firstname: 'John',
lastname: 'Doe',
image: null,
email: 'john#doe.com',
key: 0,
phone: '19191919191',
delete: false, // won't be deleted
},
In your getDataSync sort the list by delete property.
getDataSync = async () => {
try {
const list = await AsyncStorage.getItem(LIST_STORAGE_KEY);
const parsedList = JSON.parse(list);
// items with .delete property set to false, will be at the top of the list
parsedList.sort((x, y) => (x.delete === y.delete ) ? 0 : x ? 1 : -1);
this.setState({
isDataReady: true,
list: parsedList || []
});
console.log(parsedList, this.state.list);
} catch (e) {
Alert.alert('Failed to load list.');
}
}

Categories