mirror of
https://github.com/zhigang1992/graphql-engine.git
synced 2026-05-26 03:17:40 +08:00
learn: add custom graphiql for react native (#2169)
This commit is contained in:
committed by
Shahidh K Muhammed
parent
36e49ea75b
commit
83234ef48a
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,7 @@
|
||||
"hoist-non-react-statics": "^1.0.3",
|
||||
"invariant": "^2.2.0",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"jwt-decode": "^2.2.0",
|
||||
"less": "^3.7.1",
|
||||
"lru-memoize": "^1.0.0",
|
||||
"map-props": "^1.0.0",
|
||||
|
||||
@@ -816,10 +816,10 @@ label
|
||||
}
|
||||
|
||||
.common_checkbox:checked + .common_checkbox_label:before {
|
||||
content: url('./tick.png');
|
||||
background: #FFCA27;
|
||||
color: #fff;
|
||||
padding-top: 4px;
|
||||
content: url('./tick.png');
|
||||
background: #FFCA27;
|
||||
color: #fff;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.authPanelSubHeadings {
|
||||
@@ -865,3 +865,58 @@ label
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loginTabs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.loginTabsHeader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.loginFormWrapper {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.loginTabActive {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0.5;
|
||||
border-bottom: solid;
|
||||
border-bottom-color: #5f5f5f;
|
||||
padding-bottom: 5px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.loginTabInactive {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0.5;
|
||||
padding-bottom: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.loginFormElement {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.formTextbox {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isReactNative } from './utils';
|
||||
import CustomAuth from './CustomAuth'
|
||||
|
||||
class ApiRequestDetails extends Component {
|
||||
login() {
|
||||
@@ -15,7 +17,7 @@ class ApiRequestDetails extends Component {
|
||||
|
||||
const styles = require('./ApiExplorer.scss');
|
||||
|
||||
const loginButton = (
|
||||
let loginButton = (
|
||||
<button
|
||||
id="qsLoginBtn"
|
||||
className={'btn btn-primary'}
|
||||
@@ -25,7 +27,13 @@ class ApiRequestDetails extends Component {
|
||||
</button>
|
||||
);
|
||||
|
||||
const logoutButton = (
|
||||
const isCustomAuth = isReactNative();
|
||||
|
||||
if (isCustomAuth) {
|
||||
loginButton = <CustomAuth />
|
||||
}
|
||||
|
||||
let logoutButton = (
|
||||
<button
|
||||
id="qsLogoutBtn"
|
||||
className={'btn btn-danger'}
|
||||
@@ -35,6 +43,18 @@ class ApiRequestDetails extends Component {
|
||||
</button>
|
||||
);
|
||||
|
||||
if (isCustomAuth) {
|
||||
logoutButton = (
|
||||
<button
|
||||
id="qsLogoutBtn"
|
||||
className={'btn btn-danger'}
|
||||
onClick={this.logout.bind(this)}
|
||||
>
|
||||
Log Out
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
const loginOverlay = (
|
||||
<div className={styles.overlay}>
|
||||
<div className={styles.overlayContent}>
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
import React from 'react';
|
||||
import styles from './ApiExplorer.scss';
|
||||
import { signup, login } from './customAuthActions';
|
||||
import { emailRegex } from './utils';
|
||||
import jwtDecoder from 'jwt-decode';
|
||||
|
||||
class CustomAuth extends React.Component {
|
||||
|
||||
state = {
|
||||
tabIndex: 0,
|
||||
email: "",
|
||||
password: "",
|
||||
loading: false
|
||||
}
|
||||
|
||||
handleEmailChange = (e) => {
|
||||
this.setState({
|
||||
email: e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
handlePasswordChange = (e) => {
|
||||
this.setState({
|
||||
password: e.target.value
|
||||
});
|
||||
}
|
||||
|
||||
performSignup = (e, p) => {
|
||||
const successCallback = () => { this.setState({
|
||||
loading: false
|
||||
})
|
||||
|
||||
this.setState({
|
||||
tabIndex: 0,
|
||||
loading: false
|
||||
});
|
||||
alert('Successfully signed up! Please login.')
|
||||
}
|
||||
const errorCallback = (e) => {
|
||||
this.setState({
|
||||
loading: false
|
||||
});
|
||||
alert(
|
||||
`
|
||||
${e.title}
|
||||
${e.message}
|
||||
`
|
||||
)
|
||||
}
|
||||
signup(this.state.email, this.state.password, successCallback, errorCallback);
|
||||
}
|
||||
|
||||
performLogin = () => {
|
||||
const successCallback = (response) => {
|
||||
this.setState({
|
||||
tabIndex: 0,
|
||||
email: '',
|
||||
password: '',
|
||||
});
|
||||
const decodedToken = jwtDecoder(response.token);
|
||||
window.localStorage.setItem('@learn.hasura.io:graphiql-react-native-token', response.token);
|
||||
window.localStorage.setItem('@learn.hasura.io:graphiql-react-native-exp', decodedToken.exp);
|
||||
window.location.replace(window.location.href);
|
||||
}
|
||||
const errorCallback = (e) => {
|
||||
this.setState({
|
||||
loading: false
|
||||
})
|
||||
alert(
|
||||
`
|
||||
${e.title}
|
||||
${e.message}
|
||||
`
|
||||
)
|
||||
}
|
||||
login(this.state.email, this.state.password, successCallback, errorCallback);
|
||||
}
|
||||
|
||||
submit = () => {
|
||||
this.setState({ loading: true });
|
||||
if (this.state.tabIndex === 0) {
|
||||
this.performLogin(this.state.email, this.state.password)
|
||||
} else {
|
||||
this.performSignup(this.state.email, this.state.password)
|
||||
}
|
||||
}
|
||||
|
||||
toggleTab = (i) => {
|
||||
this.setState({
|
||||
tabIndex: i
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { email, password, tabIndex, loading } = this.state;
|
||||
const { handleEmailChange, handlePasswordChange } = this;
|
||||
const toggleLogin = () => this.toggleTab(0);
|
||||
const toggleSignup = () => this.toggleTab(1);
|
||||
let buttonText = tabIndex === 0 ? 'Log in' : 'Sign up';
|
||||
if (loading) {
|
||||
buttonText = "Please wait...";
|
||||
}
|
||||
let loginTabStyle, signupTabStyle;
|
||||
if (tabIndex === 0) {
|
||||
loginTabStyle = styles.loginTabActive;
|
||||
signupTabStyle = styles.loginTabInactive;
|
||||
} else {
|
||||
loginTabStyle = styles.loginTabInactive;
|
||||
signupTabStyle = styles.loginTabActive;
|
||||
}
|
||||
return (
|
||||
<div className={styles.loginTabs}>
|
||||
<div className={styles.loginTabsHeader}>
|
||||
<div className={loginTabStyle} onClick={toggleLogin}>
|
||||
Login
|
||||
</div>
|
||||
<div className={signupTabStyle} onClick={toggleSignup}>
|
||||
Signup
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.loginFormWrapper}>
|
||||
<Form
|
||||
email={email}
|
||||
password={password}
|
||||
handleEmailChange={handleEmailChange}
|
||||
handlePasswordChange={handlePasswordChange}
|
||||
buttonText={buttonText}
|
||||
loading={loading}
|
||||
submit={this.submit}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Form = ({
|
||||
email,
|
||||
handleEmailChange,
|
||||
password,
|
||||
handlePasswordChange,
|
||||
submit,
|
||||
loading,
|
||||
buttonText
|
||||
}) => {
|
||||
|
||||
const validateAndSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
if (!emailRegex.test(email.toLowerCase())) {
|
||||
alert('Invalid email', 'Please enter a valid email address');
|
||||
return;
|
||||
}
|
||||
if (!email || !password) {
|
||||
alert('Email or password cannot be empty');
|
||||
return;
|
||||
}
|
||||
submit();
|
||||
}
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={validateAndSubmit}
|
||||
>
|
||||
<div className={styles.loginFormElement}>
|
||||
<input
|
||||
value={email}
|
||||
type="text"
|
||||
onChange={handleEmailChange}
|
||||
placeholder="Email"
|
||||
className="form-control"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.loginFormElement}>
|
||||
<input
|
||||
value={password}
|
||||
type="password"
|
||||
onChange={handlePasswordChange}
|
||||
placeholder="Password"
|
||||
className="form-control"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.loginFormElement}>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary"
|
||||
disabled={loading}
|
||||
>
|
||||
{buttonText}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default CustomAuth;
|
||||
@@ -0,0 +1,94 @@
|
||||
export const signup = (email, password, successCb, errorCb) => {
|
||||
fetch(
|
||||
'https://learn.hasura.io/auth/signup',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: email,
|
||||
password
|
||||
})
|
||||
}
|
||||
)
|
||||
.then(resp => resp.json()
|
||||
.then(respObj => {
|
||||
if (resp.status === 200) {
|
||||
successCb(respObj);
|
||||
return;
|
||||
}
|
||||
if (respObj.errors && respObj.errors.length > 0) {
|
||||
errorCb({
|
||||
title: 'Error',
|
||||
message: respObj.errors[0].message
|
||||
})
|
||||
return;
|
||||
} else if (respObj.message && respObj.message.includes('unique')) {
|
||||
errorCb({
|
||||
title: 'This email is already signed up',
|
||||
message: 'Try logging in'
|
||||
})
|
||||
return;
|
||||
}
|
||||
errorCb({
|
||||
title: 'Unknown Error',
|
||||
message: 'Please try again'
|
||||
})
|
||||
})
|
||||
)
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
errorCb({
|
||||
title: 'Unexpected',
|
||||
message: 'Please try again'
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
export const login = (email, password, successCb, errorCb) => {
|
||||
fetch(
|
||||
'https://learn.hasura.io/auth/login',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: email,
|
||||
password
|
||||
})
|
||||
}
|
||||
)
|
||||
.then(resp => {
|
||||
console.log(resp);
|
||||
resp.json()
|
||||
.then(respObj => {
|
||||
console.log(respObj);
|
||||
if (resp.status === 200) {
|
||||
successCb(respObj);
|
||||
return;
|
||||
}
|
||||
if (respObj.error) {
|
||||
errorCb({
|
||||
title: 'Error',
|
||||
message: respObj.error
|
||||
});
|
||||
return;
|
||||
}
|
||||
errorCb({
|
||||
title: 'Unknown Error',
|
||||
message: 'Please try again'
|
||||
})
|
||||
})}
|
||||
)
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
errorCb({
|
||||
title: 'Unexpected',
|
||||
message: 'Please try again'
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
import { isReactNative } from './utils';
|
||||
const existingHeaders = window.__env.headers;
|
||||
const authToken = window.localStorage.getItem('auth0:id_token');
|
||||
|
||||
let authToken;
|
||||
|
||||
if (!isReactNative()) {
|
||||
authToken = window.localStorage.getItem('auth0:id_token');
|
||||
} else {
|
||||
authToken = window.localStorage.getItem('@learn.hasura.io:graphiql-react-native-token');
|
||||
}
|
||||
|
||||
|
||||
const defaultHeader = [
|
||||
{
|
||||
|
||||
@@ -9,4 +9,14 @@ const getHeadersAsJSON = headers => {
|
||||
return headerJSON;
|
||||
};
|
||||
|
||||
export { getHeadersAsJSON };
|
||||
const isReactNative = () => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.get('tutorial') === 'react-native') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
|
||||
export { getHeadersAsJSON, isReactNative, emailRegex };
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import auth0 from "auth0-js";
|
||||
import { AUTH_CONFIG } from "./auth0-variables";
|
||||
import { isReactNative } from '../ApiExplorer/utils';
|
||||
|
||||
export default class Auth {
|
||||
auth0 = new auth0.WebAuth({
|
||||
@@ -47,6 +48,12 @@ export default class Auth {
|
||||
}
|
||||
|
||||
logout() {
|
||||
if (isReactNative()) {
|
||||
window.localStorage.removeItem('@learn.hasura.io:graphiql-react-native-token');
|
||||
window.localStorage.removeItem('@learn.hasura.io:graphiql-react-native-exp');
|
||||
window.location.replace("/graphql/graphiql?tutorial=react-native");
|
||||
return;
|
||||
}
|
||||
// Clear access token and ID token from local storage
|
||||
localStorage.removeItem("auth0:access_token");
|
||||
localStorage.removeItem("auth0:id_token");
|
||||
@@ -60,7 +67,18 @@ export default class Auth {
|
||||
isAuthenticated() {
|
||||
// Check whether the current time is past the
|
||||
// access token's expiry time
|
||||
let expiresAt = JSON.parse(localStorage.getItem("auth0:expires_at"));
|
||||
return new Date().getTime() < expiresAt;
|
||||
if (!isReactNative()) {
|
||||
let expiresAt = JSON.parse(localStorage.getItem("auth0:expires_at"));
|
||||
return new Date().getTime() < expiresAt;
|
||||
} else {
|
||||
const token = window.localStorage.getItem('@learn.hasura.io:graphiql-react-native-token');
|
||||
const exp = window.localStorage.getItem('@learn.hasura.io:graphiql-react-native-exp');
|
||||
if (!exp || !token) {
|
||||
return false;
|
||||
}
|
||||
var currentTime = Math.floor(new Date().getTime() / 1000);
|
||||
return currentTime < exp;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-59768903-1');
|
||||
</script>
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
@@ -62,4 +61,4 @@
|
||||
<script src="https://storage.googleapis.com/graphql-engine-cdn.hasura.io/learn-hasura/graphiql/main.js" charset="UTF-8"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -20,14 +20,14 @@ to use and integrate APIs in your app without requiring
|
||||
external documentation tools.
|
||||
|
||||
You can access the GraphiQL for this realtime todo app tutorial here:
|
||||
[learn.hasura.io/graphql/graphiql](https://learn.hasura.io/graphql/graphiql)
|
||||
[learn.hasura.io/graphql/graphiql?tutorial=react-native](https://learn.hasura.io/graphql/graphiql?tutorial=react-native)
|
||||
|
||||
When you work with a GraphQL API in a project you will almost always
|
||||
use a tool like GraphiQL to explore and test your GraphQL queries.
|
||||
|
||||
## Basic GraphQL query
|
||||
|
||||
1. Open GraphiQL at: [learn.hasura.io/graphql/graphiql](https://learn.hasura.io/graphql/graphiql).
|
||||
1. Open GraphiQL at: [learn.hasura.io/graphql/graphiql?tutorial=react-native](https://learn.hasura.io/graphql/graphiql?tutorial=react-native).
|
||||
You'll have to login to get an auth token to query the API. In a real-world scenario
|
||||
your GraphQL APIs will be protected.
|
||||
2. You'll see a URL, and headers that contain the auth
|
||||
@@ -45,7 +45,7 @@ use a tool like GraphiQL to explore and test your GraphQL queries.
|
||||
4. Hit `ctrl + enter` or `cmd + enter` (mac) or click on the ▶️ icon to run the GraphQL query
|
||||
5. On the right, you should see a list of users by their names that are in the system!
|
||||
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql" target="_blank">Try it out in GraphiQL</a></b>
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql?tutorial=react-native" target="_blank">Try it out in GraphiQL</a></b>
|
||||
|
||||
Recall that there is no magic here! The hosted GraphiQL app is sending a GraphQL query string
|
||||
to the server at the given endpoint with the HTTP headers. The server then sends the response
|
||||
@@ -77,7 +77,7 @@ This GraphQL query will fetch all the users and their publicly visible todos:
|
||||
}
|
||||
```
|
||||
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql" target="_blank">Try it out in GraphiQL</a></b>
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql?tutorial=react-native" target="_blank">Try it out in GraphiQL</a></b>
|
||||
|
||||
|
||||
### Fetch online users and their profile information
|
||||
@@ -96,7 +96,7 @@ and their profile information (which is just their name for now):
|
||||
}
|
||||
```
|
||||
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql" target="_blank">Try it out in GraphiQL</a></b>
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql?tutorial=react-native" target="_blank">Try it out in GraphiQL</a></b>
|
||||
|
||||
|
||||
## Adding parameters (arguments) to GraphQL queries
|
||||
@@ -120,7 +120,7 @@ query {
|
||||
}
|
||||
```
|
||||
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql" target="_blank">Try it out in GraphiQL</a></b>
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql?tutorial=react-native" target="_blank">Try it out in GraphiQL</a></b>
|
||||
|
||||
The most important bit to check here is `limit: 10`. GraphQL servers will provide a list of
|
||||
arguments that can be used in `()` next to specific fields. In our case, we are using
|
||||
@@ -145,7 +145,7 @@ query {
|
||||
Notice that we are passing arguments to different fields. This GraphQL query reads as:
|
||||
> Fetch users (with limit 1), and their todos (ordered by descending creation time, and limited to 5).
|
||||
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql" target="_blank">Try it out in GraphiQL</a></b>
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql?tutorial=react-native" target="_blank">Try it out in GraphiQL</a></b>
|
||||
|
||||
<a name="query-variables"></a>
|
||||
## GraphQL variables: Passing arguments to your queries dynamically
|
||||
@@ -193,7 +193,7 @@ Let's try this out in GraphiQL:
|
||||
3. Scroll to the bottom of the page, where you see a smaller panel "Query Variables"
|
||||
4. Add the query variable as a JSON object
|
||||
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql" target="_blank">Try it out in GraphiQL</a></b>
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql?tutorial=react-native" target="_blank">Try it out in GraphiQL</a></b>
|
||||
|
||||
## Summary
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ mutation {
|
||||
```
|
||||
|
||||
<!-- [//]: # TODO: -->
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql" target="_blank">Try it out in GraphiQL</a></b>
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql?tutorial=react-native" target="_blank">Try it out in GraphiQL</a></b>
|
||||
|
||||
## Returning data after the mutation
|
||||
Notice that the data of the todo that is to be inserted is sent as
|
||||
@@ -71,7 +71,7 @@ mutation {
|
||||
```
|
||||
|
||||
<!-- [//]: # TODO: -->
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql" target="_blank">Try it out in GraphiQL</a></b>
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql?tutorial=react-native" target="_blank">Try it out in GraphiQL</a></b>
|
||||
|
||||
## Parametrise what you insert
|
||||
|
||||
@@ -103,7 +103,7 @@ mutation($todo: insert_todo_input!){
|
||||
```
|
||||
|
||||
<!-- [//]: # TODO: -->
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql" target="_blank">Try it out in GraphiQL</a></b>
|
||||
<b><a href="https://learn.hasura.io/graphql/graphiql?tutorial=react-native" target="_blank">Try it out in GraphiQL</a></b>
|
||||
|
||||
We'll explore more mutations to update or delete data a little later.
|
||||
This is a good start to grokking mutations!
|
||||
|
||||
@@ -14,7 +14,7 @@ they allow you to build great experiences without having to deal with websocket
|
||||
|
||||
## Make your first GraphQL subscription
|
||||
|
||||
1. Step 1: Head to https://learn.hasura.io/graphql/graphiql
|
||||
1. Step 1: Head to https://learn.hasura.io/graphql/graphiql?tutorial=react-native
|
||||
2. Step 2: Write this GraphQL query in the textarea:
|
||||
|
||||
```graphql
|
||||
|
||||
@@ -30,7 +30,7 @@ Let's define a graphql query to do a mutation into todos.
|
||||
|
||||
You will also need to pass in the values for the variables.
|
||||
|
||||
[Try](https://learn.hasura.io/graphql/graphiql) this mutation in GraphiQL against the application database to see what the response looks like.
|
||||
[Try](https://learn.hasura.io/graphql/graphiql?tutorial=react-native) this mutation in GraphiQL against the application database to see what the response looks like.
|
||||
|
||||
Let's now integrate this graphql mutation into our react app.
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ query getMyTodos {
|
||||
}
|
||||
```
|
||||
|
||||
[Try](https://learn.hasura.io/graphql/graphiql) this query in GraphiQL against the application database to see what the response looks like.
|
||||
[Try](https://learn.hasura.io/graphql/graphiql?tutorial=react-native) this query in GraphiQL against the application database to see what the response looks like.
|
||||
|
||||
**Note**: You need to pass the `Authorization: Bearer <token>` header before querying to get the results. The token is auto-filled in the UI after logging in via Auth0.
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ What does this query do?
|
||||
------------------------
|
||||
The query fetches `todos` with a simple condition; `is_public` must be false. We sort the todos descending by its `created_at` time according to the schema. We specify which fields we need for the todos node.
|
||||
|
||||
[Try](https://learn.hasura.io/graphql/graphiql) out this query now!
|
||||
[Try](https://learn.hasura.io/graphql/graphiql?tutorial=react-native) out this query now!
|
||||
|
||||
Introducing query variables
|
||||
---------------------------
|
||||
|
||||
@@ -25,7 +25,7 @@ After you login, you should get something like this:
|
||||
|
||||
### Load GraphiQL to play with your GraphQL APIs
|
||||
|
||||
1. Head to https://learn.hasura.io/graphql/graphiql
|
||||
1. Head to https://learn.hasura.io/graphql/graphiql?tutorial=react-native
|
||||
2. Log in (so that you can test the GraphQL APIs with a valid user token)
|
||||
|
||||
This is what you should see after the steps above:
|
||||
|
||||
@@ -35,6 +35,6 @@ Let's define a graphql query to do a mutation into todos.
|
||||
|
||||
You will also need to pass in the values for the variables.
|
||||
|
||||
[Try](https://learn.hasura.io/graphql/graphiql) this mutation in GraphiQL against the application database to see what the response looks like.
|
||||
[Try](https://learn.hasura.io/graphql/graphiql?tutorial=react-native) this mutation in GraphiQL against the application database to see what the response looks like.
|
||||
|
||||
Let's now integrate this graphql mutation into our react native app.
|
||||
|
||||
@@ -20,6 +20,6 @@ mutation ($id: Int) {
|
||||
}
|
||||
```
|
||||
|
||||
[Try](https://learn.hasura.io/graphql/graphiql) this mutation in GraphiQL against the application database to see what the response looks like.
|
||||
[Try](https://learn.hasura.io/graphql/graphiql?tutorial=react-native) this mutation in GraphiQL against the application database to see what the response looks like.
|
||||
|
||||
Let's now integrate this graphql mutation into our react app.
|
||||
Reference in New Issue
Block a user