本文是graphql极简入门教程的第三篇,本篇主要讲述在react中对接graphql的新增和查询操作
graphql极简入门教程目录:
- 第一篇:基于react和graphql-yoga搭建前后端,并实现一个hello world
- 第二篇:基于prisma及sqlite,通过playground创建及查询数据
- 第三篇:在react中执行graphql的新增和查询操作
- 第四篇:react添加路由导航、前后端搜索功能
- 第五篇:添加分页及排序功能
- 第六篇:后端编写用户登录及注册功能
- 第七篇:前端对接用户系统
- 第八篇:前后端接入github的Oauth系统
- 第九篇:graphql实时订阅
在react中展示数据
目前创建和查询的数据,都局限在playground中。接下来将要把后端的数据,真实的展示在前端中。
首先在src/components目录下,创建Link.js文件,在此文件中编写链接项的展示组件
// 文件路径:src/components/Link.js
import React from 'react';
//①
import {timeDifferenceForDate} from '../utils';
const Link = (props) => {
const {link} = props;
return (
<div className="ml1">
<div>
{link.description} ({link.url})
</div>
{(
<div className="f6 lh-copy gray">
{timeDifferenceForDate(link.createdAt)}
</div>
)}
</div>
);
};
export default Link;
回忆一下hackernews对于创建时间展示的处理:
在这里展示风格为58 minutes ago,因此在下面将会创建一个timeDifferenceForDate方法处理createdAt字段。在①中提前先引入该方法
在src目录下创建utils.js文件:
// 文件路径:src/utils.js
function timeDifference(current, previous) {
const milliSecondsPerMinute = 60 * 1000;
const milliSecondsPerHour = milliSecondsPerMinute * 60;
const milliSecondsPerDay = milliSecondsPerHour * 24;
const milliSecondsPerMonth = milliSecondsPerDay * 30;
const milliSecondsPerYear = milliSecondsPerDay * 365;
const elapsed = current - previous;
if (elapsed < milliSecondsPerMinute / 3) {
return 'just now';
}
if (elapsed < milliSecondsPerMinute) {
return 'less than 1 minute ago';
} else if (elapsed < milliSecondsPerHour) {
return (
Math.round(elapsed / milliSecondsPerMinute) +
' minutes ago'
);
} else if (elapsed < milliSecondsPerDay) {
return (
Math.round(elapsed / milliSecondsPerHour) + ' hours ago'
);
} else if (elapsed < milliSecondsPerMonth) {
return (
Math.round(elapsed / milliSecondsPerDay) + ' days ago'
);
} else if (elapsed < milliSecondsPerYear) {
return (
Math.round(elapsed / milliSecondsPerMonth) + ' months ago'
);
} else {
return (
Math.round(elapsed / milliSecondsPerYear) +
' years ago'
);
}
}
export function timeDifferenceForDate(date) {
const now = new Date().getTime();
const updated = new Date(date).getTime();
return timeDifference(now, updated);
}
接下来,在src/components目录下,创建LinkList.js文件,在此文件中编写链接列表组件:
import React from 'react';
import Link from './Link';
import {useQuery} from "urql";
// ①
const feedQuery = `
query {
feed {
links {
id
createdAt
url
description
}
}
}
`;
const LinkList = () => {
// ②
const [result] = useQuery({
query: feedQuery,
});
// ③
const { data, fetching, error } = result;
return (
<div>
{fetching && <p>Loading...</p>}
{error && <pre>{JSON.stringify(error, null, 2)}</pre>}
{data && (
data.feed.links.map((link) => (
<Link key={link.id} link={link} />
))
)}
</div>
);
};
export default LinkList;
在①中,定义了一个查询语句,与之前在playground中传入的语句一致。
在②中,将查询语句作为参数传给useQuery钩子,并解构出返回的结果result
在③中,我们解构出
data: graphql返回的查询结果数据fetching:当前是否正在请求后端接口error:错误信息
接下来,打开http://localhost:3000页面就可以看到,之前写入的两条链接数据了
在react中新建数据
要创建数据需要先有一个表单,因此在src/components目录下,创建CreateLink.js文件,在此文件中编写创建链接的Form表单:
import React, { useState } from 'react';
const CreateLink = () => {
const [formState, setFormState] = useState({
description: '',
url: ''
});
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
}}
>
<div className="flex flex-column mt3">
<input
className="mb2"
value={formState.description}
onChange={(e) =>
setFormState({
...formState,
description: e.target.value
})
}
type="text"
placeholder="A description for the link"
/>
<input
className="mb2"
value={formState.url}
onChange={(e) =>
setFormState({
...formState,
url: e.target.value
})
}
type="text"
placeholder="The URL for the link"
/>
</div>
<button type="submit">Submit</button>
</form>
</div>
);
};
export default CreateLink;
接下来,需要编写创建链接的语句,请注意这里与之前在playground中的写法有一些不同,请注意两者的差别:
react中的语句:
const createLinkMutation = `
mutation PostMutation(
$description: String!
$url: String!
) {
post(description: $description, url: $url) {
id
createdAt
url
description
}
}
`;
playground中的语句
可以看到在react中,mutation的语句更加类似于在写typescript时,对于函数类型的定义。在仔细观察之后,不难学会。
接下来,就需要urql中的useMutation钩子,来做相关的调用工作
import {useMutation} from "urql";
const [createLinkResult, createLink] = useMutation(createLinkMutation);
const { data, fetching, error } = createLinkResult;
这里可以看到,useMutation与useQuery返回的result数据结构是一致的
接下来,需要将上面的这些内容都添加src/components/CreateLink.js文件中:
import React, { useState } from 'react';
import {useMutation} from "urql";
export const createLinkMutation = `
mutation PostMutation(
$description: String!
$url: String!
) {
post(description: $description, url: $url) {
id
createdAt
url
description
}
}
`;
const CreateLink = () => {
const [formState, setFormState] = useState({
description: '',
url: ''
});
const [createLinkResult, createLink] = useMutation(createLinkMutation);
const { data, fetching, error } = createLinkResult;
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
createLink(formState);
}}
>
<div className="flex flex-column mt3">
<input
className="mb2"
value={formState.description}
onChange={(e) =>
setFormState({
...formState,
description: e.target.value
})
}
type="text"
placeholder="A description for the link"
/>
<input
className="mb2"
value={formState.url}
onChange={(e) =>
setFormState({
...formState,
url: e.target.value
})
}
type="text"
placeholder="The URL for the link"
/>
</div>
<button disabled={fetching} type="submit">Submit {fetching && '(sending...)'}</button>
</form>
</div>
);
};
export default CreateLink;
并且在src/components/App.js中引入该组件:
import React, { Component } from 'react';
import LinkList from './LinkList';
import CreateLink from "./CreateLink";
class App extends Component {
render() {
return (
<>
<CreateLink />
<LinkList />
</>
);
}
}
export default App;
此时,你在http://localhost:3000页面中,就可以直接创建链接了
为了测试笔者添加了两次,因此添加后的结果如下:
至此,我们的前后端联调已经完成!现在你已经可以在前端进行创建和查询操作了( ^▽^ )✌🏻
下一章节将会为react前端添加路由,并实现搜索功能
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情