How to update GraphQL query on button click - reactjs

I'm looking for a good way to update the "orderBy: createdAt_ASC" portion of the below graphql query when one of the two buttons below are clicked.
The default order is createAt_ASC and want the user to be able to switch between them.
const ALL_ITEMS_QUERY = gql`
query ALL_ITEMS_QUERY {
items(orderBy: createdAt_ASC) {
id
title
description
image
}
}
`;
Buttons:
<button onClick={sortNew}>Newest</button>
<button onClick={sortOld}>Oldest</button>

First of all, change your query
const ALL_ITEMS_QUERY = gql`
query ALL_ITEMS_QUERY($orderBy: String!) {
items(orderBy: $orderBy) {
id
title
description
image
}
}
`;
On react component use react-apollo
import { compose, graphql } from 'react-apollo'
class ReactComponentName extends Component {
......
//Inside render return this buttons
<button onClick={this.changeOrder.bind(this,"sortNew")}>Newest</button>
<button onClick={this.changeOrder.bind(this,"sortOld")}>Oldest</button>
.......
// And change your export statement and using HOC
export default compose(
graphql(ALL_ITEMS_QUERY, { name: 'allItemQuery' }),
// import query and bind this into props using compose
)(ReactComponentName)
onClick call a function
async changeOrder(order) {
const { allItemQuery } = this.props
const result = await allItemQuery({ variables: { 'orderBy': order } })
//Set state or store filter data
}
Change your state variable or render result data.
Or
Do this cool Query component in Apollo client

Related

Show ApolloClient mutation result

This is my first time using Apollo and React so I'll try my best.
I have a GraphQl API from which I consume some data through ApolloClient mutations. The problem is that I don't know how to show the resulting information outside of the .result. I've tried to do so with a class that has a function to consume some data and a render to show it.
The mutation works and shows the data on the console but the page remains blank when the page is loaded, so the problem I've been stuck on is, how do I show this data?
Btw, if there's any advice on how to insert data from a form using this same mutation method I'd pretty much appreciate it.
Thanks in advance.
import React, { useEffect, useState, Component } from 'react';
import { graphql } from 'react-apollo';
import './modalSignUp.css';
import{header} from './Header.js';
import ReactDOM from "react-dom";
import { ApolloProvider, Query, mutation } from "react-apollo";
import { ApolloClient, InMemoryCache, gql, useMutation } from '#apollo/client';
export const client = new ApolloClient({
uri: 'http://localhost:4011/api',
cache: new InMemoryCache(),
});
client.mutate({
mutation: gql`
mutation signin{
login(data:{
username:"elasdfg",
password:"12345678"}){
id,roles,email,username}
}
`
}).then(result => console.log(result));
export class UserList extends Component {
displayUsers() {
console.log(this.result)
var data = this.props.data;
return data.login.map((user) => {
return (
<li>{user.email}</li>
);
})
}
render() {
return (
<div>
<li>
{this.displayUsers()}
</li>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
Mutation result
I've tried to use a class to fetch the data given by the mutation and later render it in the component. I've also tried passing the result to a variable but I had no success with that.
I'm just expecting to see the data resulting from the mutation
You should request data inside the component and then save it to the state.
export class UserList extends Component {
constructor() {
this.state = {
newData: null,
};
this.mutateData = this.mutateData.bind(this);
}
mutateData() {
client
.mutate({
mutation: gql`
mutation signin {
login(data: { username: "elasdfg", password: "12345678" }) {
id
roles
email
username
}
}
`,
})
.then((result) => {
this.setState({ newData: result });
});
}
componentDidMount() {
this.mutateData();
}
render() {
// do something with new data
}
}

How to pass an argument to a components query (non-static)?

I am trying to create a component that I later can reuse on my website like so <TimeToRead id={someId}/>. My idea was to pass that id further down into the query.
However that does not work and ends up in: TypeError: Cannot read property 'edges' of undefined. Why is that so and what am I doing wrong here?
Is createPage(... context: id: someId) inside gatsby-node.js the only way to pass arguments? But that would only apply to templates...
How can I pass arguments to components?
import React from "react"
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome"
import { faClock } from "#fortawesome/free-solid-svg-icons"
import { graphql } from "gatsby"
const TimeToRead = ({id}) => {
console.log(id)
return (
<React.Fragment>
<FontAwesomeIcon icon={faClock} /> {timeToReadQuery.allMarkdownRemark.edges.node.timeToRead} ~ min.
</React.Fragment>
)
}
export const timeToReadQuery = graphql`
query timeToReadQuery($id: String!) {
allMarkdownRemark(
filter: { id: { eq: $id } }
) {
edges {
node {
timeToRead
}
}
}
}
`
export default TimeToRead
In Gatsby there are two types of queries. Page queries that can be defined in page components only and accept arguments passed as context in createdPage() and static queries which don't access variables and can be used in everywhere but are limited to one per file.
If you TimeToRead component file is not a page component then you have 2 options:
Use a static query - you just can't have variables in it.
Define a graphql fragment to use into parent page component.
// in child component
export const remarkTimeToReadFragment = graphql`
fragment RemarkTimeToRead on Query {
postTimeToRead: markdownRemark(id: { eq: $id }) {
timeToRead
}
}`
// in page component
export const pageQuery = graphql`
query PageQuery($id: String!) {
...RemarkTimeToRead
}
`
This particular example may produce a warning because $id param is not used directly in the page query and the linter just won't account for it being used by the fragment.

Using react-apollo 2.1 mutations with react lifecycle methods

I wonder, what is the way to use new Mutation components with react lifecycle methods.
Say I've got a page where I use several react-apollo mutations. I want to execute another mutation when loading state changes from true to false to show a notification popup in the page corner.
With higher order component I would do that in componentDidUpdate method, but now with <Mutation /> component I can't do that. Am I missing anything?
You can render your component in render prop function and pass mutation in props:
import gql from "graphql-tag";
import { Mutation } from "react-apollo";
const ADD_TODO = gql`
mutation addTodo($type: String!) {
addTodo(type: $type) {
id
type
}
}
`;
const AddTodo = () => {
return (
<Mutation mutation={ADD_TODO}>
{(addTodo, { data }) =>
<YourComponent someFunction={addTodo} />
}
</Mutation>
);
};
class YourComponent extends Component {
componentDidMount(){
this.props.someFunction({variables: {type: 'abc'}})
}
render(){
return <div></div>
}
}

How to create an update form with Apollo client in Reactjs

I like to edit a list of contacts I fetched from my GraphQL api with Apollo client. I see a lot of examples for add new items via mutations but I cannot find any example of updating existing items. Normally I would create a state object and make the input fields modify the properties of the state object but I'm not sure how I can modify the data I have fetched. How do I keep the view state updated?
import React, {Component} from 'react';
import gql from 'graphql-tag';
import { graphql } from 'react-apollo';
class EditContact extends Component {
_update() {
// Mutation call
}
render() {
if(this.props.contactQuery && this.props.contactQuery.loading) {
return <div>Loading</div>
}
if(this.props.contactQuery && this.props.contactQuery.error) {
return <div>Error</div>
}
const contact = this.props.contactQuery.contact;
return(
<div className="contact">
<input type="text" defaultValue={contact.firstName} onChange={??} />
<input type="submit" value="Save" onClick={this._update}>
</div>)
}
}
const CONTACT_QUERY = gql`
query contactQuery($id: Int!) {
contact(id: $id) {
id
firstName
lastName
}
}
`
export default graphql(CONTACT_QUERY, {
name: 'contactQuery',
options: ownProps => ({ variables: { id: ownProps.match.params.id } })
})(EditContact);
I know how to create and use the mutation itself but how do I keep track of the form changes and how do I set the initial data in the form fields?
You want to use a Controlled input, I learned about them here: https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/

How to force update data cache in react-apollo?

How to refetch fresh data when you revisit a page whose data is powered by react-apollo?
Say, I visit a listing page for the first time. apollo will fetch the query and caches it by default. So, when you visit the same page again during the session, it will populate the data from its cache store. How to force apollo to refetch data every time when the component mounts?
You can use apollo's fetchPolicy. Based on this, it will decide to execute the query or not again.
Example:
const graphQLOptions = {
name: 'g_schemas',
options: (props) => {
return {
variables: {
name: props.name,
},
fetchPolicy: 'cache-and-network',
}
},
}
Hope it helps.
Adding to Pranesh's answer: the fetchPolicy you're looking for is network-only.
In case you are using react-apollo's Query component, for example:
import { Query } from "react-apollo";
You can apply the fetchPolicy through its props. See below an example:
import gql from 'graphql-tag';
import React from 'react';
import { Query } from 'react-apollo';
const CounterView = ({ counter }) => (
<div>{counter}</div>
);
const GET_COUNTER = gql`
{
counter
}
`;
const Counter = () => (
<Query query={GET_COUNTER} fetchPolicy={'network-only'}>
{({ data }) => {
return <CounterView {...data} />;
}}
</Query>
);
export default Counter;
References:
https://www.apollographql.com/docs/react/essentials/queries.html#basic
https://www.apollographql.com/docs/react/essentials/queries.html#props
https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-config-options-fetchPolicy

Resources