I have a code which access data from GraphQL API in an arrow function:
const LinkList = () => {
const { loading, error, data } = useQuery(CURRENCIES);
if (loading) return <Loader/>;
if (error) return <pre>{error.message}</pre>
return (
<div className="options">
{data.currencies.map((currency) => {
return (
<button
key={currency}
id={currency}
className="option"
>
{currency.symbol}
{currency.label}
</button>
);
})}
</div>
);
};
But I really need to implement this piece of code with access to it in a class component. I was searching a documentation with accessing data in a classes, but nothing.
Any ideas?
You can use #apollo/client package and we can use client.query directly in the class component
import {
ApolloClient,
gql,
InMemoryCache,
NormalizedCacheObject
} from '#apollo/client';
const client = new ApolloClient<NormalizedCacheObject> ({
cache: new InMemoryCache({}),
uri: 'https://countries.trevorblades.com'
});
import * as React from 'react';
const GET_Countries = gql`
query {
countries{
code
name
}
}
`;
class App extends React.Component {
getData = async () => {
let res = await client.query({
query: GET_Countries
})
console.log(res)
// Set the state to make changes in UI
}
componentDidMount() {
this.getData()
}
render() {
return "Test";
}
}
export default App;
Related
I thought that relay modern implemented a system whereby it would not try to fetch data until it was rendering the component that declared it. I am talking about fragment components. I have tried to test this but it is fetching all the data.
import React from "react";
import { Environment, Network, RecordSource, Store } from "relay-runtime";
import {
RelayEnvironmentProvider,
} from "react-relay/hooks";
import "./App.css";
import QueryLoaderComponent from "./QueryLoaderComponent";
import QueryComponent from "./QueryComponent";
async function fetchGraphQL(text: string, variables: Record<any, any>) {
// Fetch data from GitHub's GraphQL API:
const response = await fetch("https://countries.trevorblades.com/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: text,
variables,
}),
});
// Get the response as JSON
return await response.json();
}
async function fetchRelay(params: any, variables: any) {
console.log(
`fetching query ${params.name} with ${JSON.stringify(variables)}`
);
return fetchGraphQL(params.text, variables);
}
// Export a singleton instance of Relay Environment configured with our network function:
const environment = new Environment({
network: Network.create(fetchRelay),
store: new Store(new RecordSource()),
});
function App() {
return (
<RelayEnvironmentProvider environment={environment}>
{/* <QueryLoaderComponent /> */}
<QueryComponent />
</RelayEnvironmentProvider>
);
}
export default App;
import { useState } from "react";
// #ts-ignore
import graphql from "babel-plugin-relay/macro";
import { QueryComponentQuery } from "./__generated__/QueryComponentQuery.graphql";
import { PreloadedQuery, useLazyLoadQuery, usePreloadedQuery } from "react-relay";
// import FragmentComponent from "./FragmentComponent";
const query = graphql`
query QueryComponentQuery($id: ID!) {
country(code: $id) {
name
...FragmentComponent_country
}
}
`;
interface Props {
// queryRef: PreloadedQuery<QueryComponentQuery>;
}
const QueryComponent = ({
// queryRef
}: Props) => {
const data = useLazyLoadQuery<QueryComponentQuery>(query, { id: "US"});
const [showContinent, setShowContinent] = useState(false);
return (
<div>
<button onClick={() => setShowContinent(!showContinent)}>
{showContinent ? "Hide" : "Show"} continent
</button>
<h1>{data.country?.name}</h1>
{/* <ul>
{data.countries.map((country: any) => (
<li key={country.name}>
{country.name}{" "}
{showContinent && <FragmentComponent country={country} />}
</li>
))}
</ul> */}
</div>
);
};
export default QueryComponent;
import { useFragment } from "react-relay";
// #ts-ignore
import graphql from "babel-plugin-relay/macro";
import { FragmentComponent_country$key } from "./__generated__/FragmentComponent_country.graphql";
export const fragment = graphql`
fragment FragmentComponent_country on Country {
continent {
name
}
}
`;
interface Props {
country: FragmentComponent_country$key;
}
const FragmentComponent = ({ country }: Props) => {
const data = useFragment(fragment, country);
return <div>{data.continent.name}</div>;
};
export default FragmentComponent;
this is fetching the data for the fragment component even though it is not rendering the fragment component. is there a way to defer it until it is rendering the component?
use
React Suspense
on the fragment or anywhere where fetching happens as wrapper
I'm trying to use next.js with apollo graphql for server-side rendering. I know that to do that i need to run the necessary queries inside getServerSideProps(), which then will pass the props into the main component, where i will be able to render the results.
I created a provider to make sure all components in the tree get the same client object.
import withApollo from "next-with-apollo";
import { ApolloClient, InMemoryCache } from "#apollo/client";
import { ApolloProvider } from "#apollo/react-hooks";
export default withApollo(
() => {
return new ApolloClient({
ssrMode: true,
uri: "https://my.api/graphql",
cache: new InMemoryCache()
});
},
{
render: ({ Page, props }) => {
return (
<ApolloProvider client={props.apollo}>
<Page {...props} />
</ApolloProvider>
);
}
}
);
but how can i get this client inside the getServerSideProps() function if it's not being wrapped by withApollo()?
import gql from "graphql-tag";
import { useQuery } from "#apollo/react-hooks";
import { ApolloClient } from "#apollo/client";
import withApollo from "next-with-apollo";
const MY_QUERY = gql`
query MyQuery {
myQuery {
name
}
}
`;
function MyComponent(props) {
return (
<div className="landing-section__topcontainer ph-lg-8 ph-3">
<div className="overflow-list-container">
<div className="landing-horizontal-list">
{props.res.map(q => {
return (
<div className="tag-tile__title">{q.name}</div>
);
})}
</div>
</div>
</div>
);
}
export async function getServerSideProps() {
// Fetch data from external API
const apolloClient = getApolloClient();
const { data } = await apolloClient.query({
query: MY_QUERY
});
const res = data.myQuery;
return { props: { res } };
}
export default withApollo(MyComponent);
hey i am new in the field and want to display the state using the map and i am not able to do so
and there is no problem in the api call through axios so ignore it
my code is
import React, { Component } from 'react';
import axios from 'axios';
const url ='https://www.reddit.com/r/space.json';
class Apicall extends Component {
state={
posts:[],
subr:'space'
};
componentDidMount(){
this.getReddit();
}
getReddit=async()=>{
console.log('getredddit called sir ');
try {
let response=await axios.get(`https://www.reddit.com/r/${this.state.subr}.json`);
let posts=response.data.data.children.map(obj=>obj.data)
this.setState({posts:posts},()=>{console.log(this.state.posts);
})
} catch (error) {console.log(error);}}
render() {
let controlItems=this.state.posts.map(post=>{<h1 id={post.id}>{post.title}</h1>});
return (
<div>
<h1>{`/r/${this.state.subr}`} </h1>
{controlItems}
</div>);
}
}
export default Apicall;
You were iterating wrong on your data. response.data.data.children should be replaced with response.data.children. Implicit return of et controlItems=this.state.posts.map(post=>{{post.title}}); is also wrong.
import React from "react";
import "./styles.css";
export default function App() {
return (
<div className="App">
<Apicall />
</div>
);
}
class Apicall extends React.Component {
state = {
posts: [],
subr: "space"
};
componentDidMount() {
this.getReddit();
}
getReddit = async () => {
console.log("getredddit called sir ");
try {
let response = await fetch(
`https://www.reddit.com/r/${this.state.subr}.json`
);
response = await response.json();
console.log(response);
let posts = response.data.children.map(obj => obj.data);
this.setState({ posts: posts }, () => {
console.log(this.state.posts);
});
} catch (error) {
console.log(error);
}
};
render() {
let controlItems = this.state.posts.map(post => (
<h1 id={post.id}>{post.title}</h1>
));
return (
<div>
<h1>{`/r/${this.state.subr}`} </h1>
{controlItems}
</div>
);
}
}
I 'm traying to send a param to getInitialProp function to made the fecth to the correct json.
here is my code:
hepler.js --> here I made the fetch per se.
export async function getEvents() {
const res = await fetch("https://url/eventos.json");
let new_data = await res.json();
return { events: new_data.data };
}
export async function getDetails(slug) {
const res = await fetch(`https://myurl/${slug}.json`);
let data_detail_event = await res.json();
return { data_detail_event };
}
_app.js // here I have the getInitialProps and works great
import App from "next/app";
import ContextProvider from "../provider/ContextProvider";
import fetch from "isomorphic-unfetch";
import {getEvents, getDetails} from '../helper/index'
export default class MyApp extends App {
static async getInitialProps() {
const events = await getEvents();
return {
events : events.events
};
}
render() {
const { Component, pageProps } = this.props;
return (
<div>
<ContextProvider events={this.props.events} >
<Component {...pageProps} />
</ContextProvider>
</div>
);
}
}
pages/[id].js
import { useRouter } from "next/router";
import Context from "../../config/Context";
/* Components */
import WordCounter from "../../components/word-counter/WordCounter";
function Post(props) {
const router = useRouter();
const context = React.useContext(Context);
return (
<React.Fragment>
<WordCounter />
</React.Fragment>
);
}
Post.getInitialProps = async ({ query}) => {
const detail = await getDetail(query.id) --> here I send the param and it seems never arrive to helper.js, why?
return {detail}
}
export default Post
Where is the problem? HELP!
THAANKS!
i think getInitialProps run in server and your helper function doesn't load there.
use fetch inside getInitialProps .
So I've run into an issue with Apollo where I'm trying to dynamically add/update/remove to a list of topics in my app, however my pollInterval in my Query keeps making network requests over and over, even after I have the data in my Apollo cache. I know there are ways to manually trigger a refetch, but that after playing around with it, it's a lot of extra steps to get it the way I want. Is there something I'm missing here?
Here is the code for the component:
import React from 'react';
import { gql } from 'apollo-boost';
import { Query, Mutation } from 'react-apollo';
import TopicForm from "./TopicForm";
import { Link, withRouter} from "react-router-dom";
const REMOVE_TOPIC = gql`
mutation REMOVE_TOPIC(
$id: String!
) {
removeTopic(id: $id) {
id
}
}
`
const GET_TOPICS = gql`
{
topics {
id
name
}
}
`;
class Topics extends React.Component {
removeTopic(id, removeTopicById) {
removeTopicById({
variables: {
id
}
}).then(result => {
// Redirect to main topics page
this.props.history.push('/topics');
})
}
componentDidMount() {
}
render() {
const RemoveButton = props => {
return <Mutation mutation={REMOVE_TOPIC}>
{(removeTopicById, { loading }) => {
return <button type="button" onClick={(e) => {
e.preventDefault();
this.removeTopic(props.id, removeTopicById);
}}>X</button>
}}
</Mutation>
}
const TopicList = () => {
return (<Query query={GET_TOPICS} pollInterval={40}>
{(({ data: { topics }, loading }) => {
if (loading || !topics) {
return <div>Loading ...</div>;
}
return topics.map(({ id, name }) => {
return <div><Link to={`/topics/${id}`}>{name}<RemoveButton id={id} /></Link></div>
})
})
}
</Query>)
}
return (<div>
{this.props.match.params.topicId ? <h2>Update Topic</h2> : <h2>Add Topic</h2>}
<TopicForm topicId={this.props.match.params.topicId}/>
<TopicList />
</div>)
}
}
export default withRouter(Topics)
The main part I'm talking about is inside the TopicList function
pollInterval is doing what it is meant to
refetchQueries isn't too complex. In this case I think it would be:
<Mutation
mutation={REMOVE_TOPIC}
refetchQueries={[{ query: GET_TOPICS }]}
With hooks you can do the following:
Use the startPolling and stopPolling dependencies like this for example:
useEffect(() => {
startPolling(10000);
return () => {
stopPolling();
};
}, [startPolling, stopPolling]);
This will refetch every 10 seconds and stopPolling when component unmount.