(五)搭建graphql项目, 前端可随意指定接口返回的数据

前言

上节课我们讲到如何使用Apollo获取到数据库的Person列表,这节课,我们将会继续使用它新增PersonJob数据

AddPerson.js

首先,我们在components文件夹下创建AddPerson.js,代码内容如下所示:

import { gql, useQuery } from '@apollo/client'

const JOBS_LIST = gql`
    {
        jobs {
            name
            id
        }
    }
`

function GetJobsList() {
    const { loading, error, data } = useQuery(JOBS_LIST)
    if (loading) return <option>Loading...</option>
    if (error) return <option>Error: {error}</option>
    return data.jobs.map(({name, id}) => {
        return <option key={id} value={id}>{name}</option>
    })
}
const AddPerson = props => {
    return (
        <form id="addPerson">
            <div className='field'>
                <label>姓名:</label>
                <input type="text"/>
            </div>
            <div className='field'>
                <label>性别:</label>
                <select>
                    <option>选择性别</option>
                    <option value="male"></option>
                    <option value="female"></option>
                </select>
            </div>
            <div className='field'>
                <label>年龄:</label>
                <input type="number"/>
            </div>
            <div className='field'>
                <label>职位:</label>
                <select>
                    <option>选择职位</option>
                    {GetJobsList()}
                </select>
            </div>
            <button>+</button>
        </form>
    )
}
export default AddPerson;

GetJobsList这个方法里返回的option里面的value值必须是jobId,它可以将PersonJob关联起来。忘记的同学可以看看我之前的文章

在这里我们创建了form表单,目前点击+按钮不会有任何反应,这个功能会在mutation里添加

App.js

App.js里增加AddPerson.js的引入,部分代码如下所示:

import AddPerson from './components/AddPerson';
function App() {
  return (
    <ApolloProvider client={client}>
      <div id="main">
        ...
        <AddPerson></AddPerson>
      </div>
    </ApolloProvider>
  );
}

刷新页面,可看到如下效果
在这里插入图片描述

queries

src目录下创建queries文件夹,在该文件夹下创建queries.js,我们将前面的gql查询代码全部移至该js文件内,代码如下所示:

import { gql } from '@apollo/client'

const JOBS_LIST = gql`
    {
        jobs {
            name
            id
        }
    }
`
const PERSON_LIST = gql`
    {
        persons {
            name
        }
    }
`

export {
    JOBS_LIST,
    PERSON_LIST
}

AddPerson.jsPersonList.js做相应的引入更改

初始化响应式数据

react提供了useState方法,可使数据变成响应式(即数据一旦更改,视图可检测到并发生变化)

AddPerson.js里添加如下功能,代码如下所示:

import { useState } from 'react'
import { useQuery } from '@apollo/client'
import { JOBS_LIST } from '../queries/queries'

function GetJobsList() {
    const { loading, error, data } = useQuery(JOBS_LIST)
    if (loading) return <option>Loading...</option>
    if (error) return <option>Error: {error}</option>
    return data.jobs.map(({name, id}) => {
        return <option key={id} value={id}>{name}</option>
    })
}
const AddPerson = props => {
    const [name, setName] = useState('')
    const [sex, setSex] = useState('')
    const [jobId, setJobId] = useState('')
    const [age, setAge] = useState(0)
    
    function submitForm(e) {
        e.preventDefault()
        console.log(name)
        console.log(sex)
        console.log(age)
        console.log(jobId)
    }
    return (
        <form id="addPerson" onSubmit={submitForm}>
            <div className='field'>
                <label>姓名:</label>
                <input type="text" onChange={e => setName(e.target.value)}/>
            </div>
            <div className='field'>
                <label>性别:</label>
                <select onChange={e => setSex(e.target.value)}>
                    <option>选择性别</option>
                    <option value="male"></option>
                    <option value="female"></option>
                </select>
            </div>
            <div className='field'>
                <label>年龄:</label>
                <input type="number" onChange={e => setAge(e.target.value)}/>
            </div>
            <div className='field'>
                <label>职位:</label>
                <select onChange={e => setJobId(e.target.value)}>
                    <option>选择职位</option>
                    {GetJobsList()}
                </select>
            </div>
            <button>+</button>
        </form>
    )
}
export default AddPerson;

submitForm方法内添加e.preventDefault(),这是js功能,目的是阻止页面自动刷新

在浏览器端,输入各个值,控制台可显示对应的值,如下图所示:
在这里插入图片描述

增加mutation

queries.js里增加ADD_PERSON_MUTATION代码,如下所示:

const ADD_PERSON_MUTATION = gql`
    mutation($name:String!,$age:Int!,$sex:String!,$jobId: ID!){
        addPerson(name:$name, age: $age, sex: $sex, jobId: $jobId) {
            name
            id
        }
    }
`
export {
    JOBS_LIST,
    PERSON_LIST,
    ADD_PERSON_MUTATION
}

注意:这里的age类型为Int,感叹号表示该参数为必传参数

AddPerson.js新增的代码如下所示:

import { useQuery, useMutation } from '@apollo/client'
import { JOBS_LIST, ADD_PERSON_MUTATION } from '../queries/queries'
const AddPerson = props => {
    const [name, setName] = useState('')
    const [sex, setSex] = useState('')
    const [jobId, setJobId] = useState('')
    const [age, setAge] = useState(0)

    const [addPerson, { data, loading, error }] = useMutation(ADD_PERSON_MUTATION)

    function submitForm(e) {
        e.preventDefault()
        try {
            addPerson({
                variables: {
                    name,
                    sex,
                    jobId,
                    age: Number(age)
                }
            })
            if (error) console.error(`Service Error: ${error}`)
            resetForm()
        } catch (err) {
            console.error(err)
        }
        
    }
    function resetForm() {
        setName('')
        setSex('')
        setAge(0)
        setJobId('')
    }
    return (
        <form id="addPerson" onSubmit={e => submitForm(e)}>
            ...
        </form>
    )
}

在浏览器表单上输入信息,点击+按钮,已成功添加,如下图所示:
在这里插入图片描述
刷新界面,lucy已显示在界面上
在这里插入图片描述

新增数据后,界面实时响应显示

如何做到数据新增成功后,界面实时显示新增的数据呢?
需在AddPerson.js里新增如下代码:

import { JOBS_LIST, PERSON_LIST, ADD_PERSON_MUTATION } from '../queries/queries'
...
function submitForm(e) {
        e.preventDefault()
        try {
            addPerson({
                variables: {
                    ...
                },
                refetchQueries: [{query: PERSON_LIST}]
            })
            ...
        } catch (err) {
            console.error(err)
        }
        
    }

界面效果如下所示:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值