Apollo GraphQL query inside of react custom hook - reactjs

I'm trying to list all the characters from Rick & Morty API. I wrote the following hook to use in my Component that is going to render the result. When I hardcoded values eg: (page: 1 , filter: { name : "Rick"}) The query runs just fine.If I try to use variables it returns an error 400 bad request (I'm assuming this means my $page / $filter values are invalid and I tried to check the values within them + their types everything seemed fine)I looked at the documentation at Apollo | Queries - Client (React) and made sure that I was using the proper syntax to inject variables into the query. The query is from the official Rick & Morty API docs API Docs. Any guidance/direction is much appreciated.
useCharecterList Hook
Params: page: Number | filter: String
import { useQuery, gql } from '#apollo/client';
const CHARECTERS_LIST = gql`
query ($page: Number!, $filter: String!){
characters
(page: $page , filter: { name : $filter}) {
info {
next
prev
}
results {
id
name
image
}
}
}
`;
export default function useCharecterList({page, filter}){
return useQuery(CHARECTERS_LIST, {
variables: {page, filter}
});
}
Component Rendering the results:
import useCharecterList from '../hooks/useCharecterList'
import { Fragment } from 'react';
import InputComponent from './InputComponent';
function CharectersList() {
const { loading, error, data } = useCharecterList({page: 1, filter: "Rick"});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
const options = data.characters.results.map(({name}) =>{
return name;
})
return(
<Fragment>
<InputComponent options={options}></InputComponent>
{
data.characters.results.map(({ id, name, image }) => (
<div key={id}>
<img src={image} alt={`${name} from the popular sitcom Rick & Morty`}/>
<p>{name}</p>
</div>
))
}
</Fragment>
)
}
export default CharectersList

I figured it out... Like an Idiot I assumed the query types are just your normal JS types. After some digging I got it to work as follows.
import { useQuery, gql } from '#apollo/client';
const CHARECTERS_LIST = gql`
query CharectersList($page: Int!, $filter: FilterCharacter!){
characters
(page: $page, filter: $filter) {
info {
next
prev
}
results {
id
name
image
}
}
}
`;
export default function useCharecterList(options){
return useQuery(CHARECTERS_LIST, options);
}
import useCharecterList from '../hooks/useCharecterList'
import { Fragment } from 'react';
import InputComponent from './InputComponent';
function CharectersList() {
const { loading, error, data } = useCharecterList({variables: {page: 1, filter: { name: "Summer" }}});
if (loading) return <p>Loading...</p>;
if (error) {
console.log(error);
return <p>Error :(</p>}
const options = data.characters.results.map(({name}) =>{
return name;
})
return(
<Fragment>
<InputComponent options={options}></InputComponent>
{
data.characters.results.map(({ id, name, image }) => (
<div key={id}>
<img src={image} alt={`${name} from the popular sitcom Rick & Morty`}/>
<p>{name}</p>
</div>
))
}
</Fragment>
)
}
export default CharectersList

Related

Problem to get an image in a blogpost with NextJS and WpGraphQL

I have another question in the project I'm doing, using NextJS to create a site with a blog part in Wordpress, through WPGraphQL, and I need support in a specific part. Let's go...
I managed to pull the highlighted image with almost no problems, I broke my head a bit, but it worked. The result that's functioning is the post excerpt, the code and the query were as follows (in time: image merely to test, it was the first idea that came to my mind, the site is not about Pokemon):
Image with working image in the excerpt, codes below
NextJS code:
import { LastPosts, PostContainer } from "./Styled";
const RecentBlogPosts = ({lastPosts}) => {
const posts = lastPosts;
return (
<LastPosts>
<h1> ÚLTIMAS POSTAGENS </h1>
{posts?.map((post) => {
return (
<PostContainer key={post.slug}>
<img src={post.featuredImage?.node.sourceUrl} alt="" />
<Link href={`/post/${post.slug}`}>
<a>
<h3> { post.title } </h3>
<div dangerouslySetInnerHTML={{ __html: post.excerpt }} />
<button> Saiba mais </button>
</a>
</Link>
</PostContainer>
)
})}
</LastPosts>
)
};
export default RecentBlogPosts;
Query for this part:
export const RECENT_POSTS = `query RecentPosts {
posts(where: {orderby: {field: DATE, order: DESC}}, first: 2) {
nodes {
id
slug
title
excerpt
featuredImage {
node {
sourceUrl
}
}
}
}
}`;
But I tried to pull the same image in the full blogpsot and it wasn't working... It appears when I view the post from the generic WordPress admin template, but not at my NextJS site, which i See through localhost:3000/post/[here would be the post title in slug] that I'm using. The rest is normal, text with all fonts and specifications with styled components, as well as tags, they work without any problem. The following is the same schema: image with result, code and query that I am using, this time for the part where I'm having problems:
Image with blogpost not working, codes below
NextJS code:
import fetcher from "../../lib/fetcher";
import { GET_ALL_POSTS_WITH_SLUG, POST_BY_SLUG } from "../../lib/wordpress/api";
import { useRouter } from "next/router";
import { Reset } from "../../constants/StyledConstants";
import Header from "../../components/Header/Header";
import { BlogArticle, BlogPostContent, TagLinks, TagWrapper } from "./StyledPost";
import Footer from "../../components/Footer/Footer";
const post = ({ postData }) => {
const blogPost = postData.data.post;
console.log(postData);
const tags = postData.data.post.tags.nodes;
const router = useRouter;
if(!router.isFallback && !blogPost?.slug) {
return <div>erro</div>
}
return (
<>
<Reset />
<Header />
<BlogPostContent>
{router.isFallback ? (
<div> Carregando...... </div>
) : (
<div>
<h1> { blogPost.title } </h1>
<img src={post.featuredImage?.node.sourceUrl} alt="imagem não aparece" />
<BlogArticle dangerouslySetInnerHTML={{ __html: blogPost.content }} />
<TagWrapper>
{tags.map((tag) => <TagLinks href={`/tags/${tag.slug}`} key={tag.slug}> { tag.name } </TagLinks>)}
</TagWrapper>
</div>
)}
</BlogPostContent>
<Footer />
</>
)
}
export default post;
export async function getStaticPaths() {
const response = await fetcher(GET_ALL_POSTS_WITH_SLUG);
const allposts = await response.data.posts.nodes;
return {
paths: allposts.map((post) => `/post/${post.slug}`) || [],
fallback: false
};
}
export async function getStaticProps({ params }) {
const variables = {
id: params.slug,
idType: "SLUG"
};
const data = await fetcher(POST_BY_SLUG, { variables })
return {
props: {
postData: data
},
};
}
Query being used:
export const POST_BY_SLUG = `query PostBySlug($id: ID!, $idType: PostIdType!) {
post(id: $id, idType: $idType) {
title
slug
date
content
featuredImage {
node {
sourceUrl
}
}
tags {
nodes {
name
slug
}
}
}
}`;
I tried to use {post.featuredImage?.node.sourceUrl} because, as far as I understand, following the same basis I did for the excerpt in the blogspot, it should work, but I guess I was wrong... I tried to think of other ways to do it to get to the image, without success... Could someone help to point out where I am wrong please? Thank you very much in advance!!

React mutation with graphql and strapi-'return' outside of function

I'm trying to update existing data collection on strapi with a new enter. using strapi and GraphQL in the backhand and react on the front.
import React from 'react'
import { useMutation, gql } from '#apollo/client'
const CREATE_REVEIW = gql`
mutation {
createReveiw(input: { data: {body:“Lorem ipsum dolor sit am”,title: “avitesttesting”, rating: 5} }) {
reveiw {
body
title
rating
} } } `;
export default function AddTodo() {
const [createReveiw, { data, loading, error }] = useMutation(CREATE_REVEIW);}
console.log(data);
if (loading) return 'Submitting...';
if (error) return `Submission error! ${error.message}`;
return (
<div className="review-card">
<div className="rating">{data.reveiw.rating}</div>
<h2>{data.reveiw.title}</h2>
{data.reveiw.categories.map(c => (
<small key={c.id}>{c.name}</small>
))}
<p>{data.reveiw.body}</p>
</div>
)
I am getting an err:
SyntaxError: C:\graphy\graphy2\src\pages\AddTodo.js: 'return' outside of function. data' is not defined loading' is not defined
Because you have } in the end of line:
const [createReveiw, { data, loading, error }] = useMutation(CREATE_REVEIW);}
So just remove it and update like this:
export default function AddTodo() {
const [createReveiw, { data, loading, error }] = useMutation(CREATE_REVEIW);
console.log(data);
if (loading) return "Submitting...";
if (error) return `Submission error! ${error.message}`;
return (
<div className="review-card">
<div className="rating">{data.reveiw.rating}</div>
<h2>{data.reveiw.title}</h2>
{data.reveiw.categories.map((c) => (
<small key={c.id}>{c.name}</small>
))}
<p>{data.reveiw.body}</p>
</div>
);
}

How to capture the response of a query in GraphQL Relay

I am new to relay, I have a query that delivers a response, which I can see in the network tab of the inspector, but what I dont understand is how to grab that response for use in my component. Could someone please explain that?
My query is
const query = graphql`
query AdvisorProfileQuery($id: ID!) {
node(id: $id) {
...on Advisor {
name
postalCode
products
referralCode
status
updatedAt
}
}
}`;
and runs through the renderer
const QueryRenderer = LoadingQueryRenderer(AdvisorProfile, query);
export default ({ i18n }) => {
return (
<>
<QueryRenderer
params={{ id: id }}
/>
</>
);
};
but what is the variable name that holds that data that is returned to the component? I want to pass that data as a prop to another component.
This is how the response looks
You can follow the example from official docs
import React from 'react';
import { QueryRenderer, graphql } from 'react-relay';
const Example = (props) => {
return (
<QueryRenderer
environment={environment}
query={graphql`
query ExampleQuery($pageID: ID!) {
page(id: $pageID) {
name
}
}
`}
variables={{
pageID: '110798995619330',
}}
render={({ props }) => {
if (props) {
return <ChildComponent page={page.name} />;
}
return <div>Loading</div>;
}}
/>
);
}
you can consume the data inside the QueryRenderer render like usual props

How can I use React component as an enhancer?

I'm a newbie and React and I've got the following piece of code:
class MyCoolComponent extends React.Component {
render() {
return (
<QueryRenderer
environment={environment}
query={graphql`
query UserQuery {
viewer {
id
}
}
`}
variables={{}}
render={({error, props}) => {
if (error) {
return <div>Error!</div>;
}
if (!props) {
return <div>Loading...</div>;
}
return <div>User ID: {props.viewer.id}</div>;
}}
/>
);
}
}
I want to use this React component as an enhancer to a different React Component to pass the data (props.viewer.id) using compose(addDataEnhancer, ...) to the other High Order Component (such that it'll be able to use props.viewer.id). How can I do it?
The context: the idea is to use this MyCoolComponent as a replacement for the data source function here:
export default compose(
// data source
graphql(gql`query MyQuery1 { ... }`),
)(MyHOCComponent);
function MyHOCComponent({ data }) {
console.log(data);
}
I think this should work. compose will call first hoc with base component, than return value (wrapped component) is passed to next hoc (next compose argument), etc...
Base component (and every HOC listed after this HOC) will have prop viewerId
// withViewerId.js
import React from 'react'
import { QueryRenderer, graphql } from 'react-relay'
import environment from 'environment'
export default (BaseComponent) => (restProps) => (
<QueryRenderer
environment={environment}
query={graphql`
query UserQuery {
viewer {
id
}
}
`}
variables={{}}
render={({error, props}) => {
if (error) {
return <div>Error!</div>;
}
if (!props) {
return <div>Loading...</div>;
}
return <BaseComponent {...restProps} viewerId={props.viewer.id} />;
}}
/>
)
usage:
import withViewerId from 'withViewerId'
export default compose(withViewerId)(BaseComponent)

Access a state value to passing it as parameter of a query

I'm having a little problem. Being a beginner in "react apollo ...", I want to pass the value of my state "selectCarcolor" as parameter of my query.This must be done when I select a color from the drop-down list.I read a lot of things in the documentation but I do not know where to start.
You can see all of my code here: Github link description here
onChangeCarColor(e){
//const selectCarcolor = this.state.selectCarcolor
this.setState({ selectCarcolor:e.target.value})
console.log("color " + this.state.selectCarcolor);
}
const Cquery = `gql query getAllUsers($color: String!) {
getAllUsers(color: $color) {
_id
name
cars {
color
}
}
}`;
const datafetch = graphql(Cquery, {
options: props=> ({
variables: { color: **Here I want to pass the select value**},
})
});
Hoping for a little help from you.
Thank you guys!
react version :16.2.0
react-apollo version : 2.0.1
You can wrap your component with withApollo function from react-apollo package which injects the ApolloClient into your component (available as this.props.client). You can send a query using it. Check official docs and this tutorial for more details and explanations.
Example:
import React, { Component } from 'react'
import { withApollo } from 'react-apollo'
import gql from 'graphql-tag'
import Link from './Link'
class Search extends Component {
state = {
links: [],
filter: ''
}
render() {
return (
<div>
<div>
Search
<input
type='text'
onChange={(e) => this.setState({ filter: e.target.value })}
/>
<button
onClick={() => this._executeSearch()}
>
OK
</button>
</div>
{this.state.links.map((link, index) => <Link key={link.id} link={link} index={index}/>)}
</div>
)
}
_executeSearch = async () => {
const { filter } = this.state
const result = await this.props.client.query({
query: FEED_SEARCH_QUERY,
variables: { filter },
})
const links = result.data.feed.links
this.setState({ links })
}
}
const FEED_SEARCH_QUERY = gql`
query FeedSearchQuery($filter: String!) {
feed(filter: $filter) {
links {
id
url
description
createdAt
postedBy {
id
name
}
votes {
id
user {
id
}
}
}
}
}
`
export default withApollo(Search)
In your datafetch() function you are setting option variables in a function on props, but you are setting your color selected to your state.
Can you just do
options: {
variables: { color: this.state.selectCarcolor, }
}
instead of what you are doing?

Resources