下一个 JS apollo 链接更改清除查询,必须刷新页面才能运行查询
Posted
技术标签:
【中文标题】下一个 JS apollo 链接更改清除查询,必须刷新页面才能运行查询【英文标题】:next JS apollo Link change clears query, have to refresh page for query to run 【发布时间】:2021-05-31 11:25:10 【问题描述】:我正在将 Next JS 与 Apollo 一起使用,并且我有以下查询可以正常工作,但是当我从页面导航到另一个页面并返回查询不运行时,我的字段为空,我必须点击刷新填充它们。有谁知道为什么会这样。
import useQuery, gql, useMutation from "@apollo/client";
import useEffect, useState from "react";
import v4 as uuidv4 from "uuid";
import Form from "../components/Form";
import Layout from "../components/Layout";
export const INPUT_VALUES = gql`
query GetInputValues
allFormInputVals
data
name
_id
type
index
`;
const FormBuilder = () =>
const blankFormInput =
__typename: "FormInputVal",
name: "test",
_id: uuidv4(),
type: "text",
;
const [formState, setFormState] = useState([blankFormInput]);
const loading, error, data = useQuery(INPUT_VALUES);
useEffect(() =>
const formData = data?.allFormInputVals?.data;
setFormState(formData);
, [data]);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: error.message</p>;
return (
<Layout>
formState && <Form formState=formState setFormState=setFormState />
</Layout>
);
;
export default FormBuilder;
更新:这里要求的是表单组件
import useEffect, useState from "react";
import useForm from "react-hook-form";
import useQuery, gql, useMutation from "@apollo/client";
import v4 as uuidv4 from "uuid";
import styled from "styled-components";
import INPUT_VALUES from "../pages/formBuilder";
import Link from "next/link";
import useSWR from "swr";
const ADD_INPUT_VALUES = gql`
mutation AddInputValues($name: String!, $type: String!, $index: Int!)
createFormInputVal(data: name: $name, index: $index, type: $type )
name
type
index
_id
`;
const UPDATE_FORM_INPUT_VAL = gql`
mutation UpdateFormInputVal(
$name: String!
$type: String!
$index: Int!
$ID: ID!
$arrayOrder: Int
)
updateFormInputVal(
id: $ID
data: name: $name, type: $type, index: $index, arrayOrder: $arrayOrder
)
name
type
index
arrayOrder
`;
const DELETE_FORM_INPUT_VAL = gql`
mutation DeleteFormInputVal($ID: ID!)
deleteFormInputVal(id: $ID)
name
`;
const FormStyles = styled.form`
display: grid;
grid-template-columns: 350px 1fr 1fr;
label
//background: red;
input,
select
//background: aqua;
border: 1px solid grey;
border-top: 0;
border-right: 0;
border-left: 0;
input[type="button"]
background: green;
border: none;
border-radius: 30px;
color: #fff;
padding: 15px;
width: 200px;
margin: 0 0 25px auto;
&:hover
cursor: pointer;
button
background: lightgray;
padding: 15px;
border: none;
&:hover
cursor: pointer;
`;
const GridStyles = styled.div`
display: grid;
grid-row-gap: 5px;
padding: 15px 0;
width: 600px;
margin: 0 auto 0 0;
div
display: grid;
grid-template-columns: 100px 1fr;
align-items: center;
`;
const AddFormStyles = styled.form`
display: grid;
grid-template-columns: 1fr 1fr;
`;
const fetcher = (url) => fetch(url).then((r) => r.json());
export default function Form( formState, setFormState )
const test = formState?.reduce((obj, item, idx) =>
return ...obj, [`name-$item._id`]: item.name ;
, );
const register, handleSubmit, errors = useForm( defaultValues: test );
const
register: register2,
handleSubmit: handleSubmit2,
errors: errors2,
= useForm();
const [formStateVals, setFormStateVals] = useState(undefined);
const [savingState, setSavingState] = useState(false);
const [deletingState, setDeletingState] = useState(false);
const data: formEntryData, error = useSWR("/api/data", fetcher);
// console.log(test);
const onSubmit = async (data) =>
let hmm = formState.map((ok, i) =>
//console.log(ok._id);
var name = data[`name-$ok._id`];
var type = data[`type-$ok._id`];
var boogie =
_id: ok._id,
name: name,
type: type,
index: i,
arrayOrder: ok.arrayOrder,
;
return boogie;
);
//1. query all formEntryData *
//2. Grab all the submitted fields
//3. run a series of replaces with the correct formEntryData
//4. as well as the updateField change
// const letsGo =
// formEntryData,
// hmm,
// ;
// const res1 = await fetch("../api/update",
// method: "POST",
// headers:
// "Content-Type": "application/json",
// ,
// body: JSON.stringify(letsGo),
// );
// console.log(formEntryData);
// console.log(hmm);
hmm.map(async (item, i) =>
const res = await updateFormInputVal(
variables:
name: item.name,
type: item.type,
index: item.index,
ID: item._id,
arrayOrder: i,
,
).catch(console.error);
//console.log(res);
);
setSavingState(true);
;
//console.log(errors);
const addInput = async (clickData) =>
console.log("data");
console.log(clickData);
console.log("data");
const res = await createFormInputVal(
variables:
name: "test",
type: clickData.chooseType,
index: 0,
,
)
.then((data) =>
const blanktext =
__typename: "FormInputVal",
name: "Test",
_id: data.data.createFormInputVal._id,
type: clickData.chooseType,
;
console.log(blanktext);
setFormState([...formState, ...blanktext ]);
)
.catch(console.error);
;
const deleteVal = async (id) =>
setDeletingState(true);
const res = await deleteFormInputVal(
variables:
ID: id,
,
).catch(console.error);
console.log(res);
;
const [createFormInputVal, data: createInputData ] = useMutation(
ADD_INPUT_VALUES
);
const [
updateFormInputVal,
data: updateInputData, loading: saving ,
] = useMutation(UPDATE_FORM_INPUT_VAL);
const [
deleteFormInputVal,
data: deleteInputData, loading: deleting ,
] = useMutation(DELETE_FORM_INPUT_VAL,
refetchQueries: [ query: INPUT_VALUES ],
);
// console.log(updateInputData);
return (
<>
<FormStyles onSubmit=handleSubmit(onSubmit)>
<h1>Create Your Form Input Fields</h1>
<div>
formState?.map((val, idx) =>
const nameId = `name-$val._id`;
const typeId = `type-$val._id`;
return (
<div key=val._id>
<GridStyles>
<div>
<label htmlFor=nameId>Input Name</label>
<input
type="text"
name=nameId
id=nameId
className=val.type
ref=register()
/>
</div>
<div>
val.type
/* <label htmlFor=typeId>Input Type</label>
<select
defaultValue=val.type
name=typeId
ref=register
>
<option value="text">text</option>
<option value=" image"> image</option>
</select> */
</div>
<button onClick=() => deleteVal(val._id) type="button">
Delete
</button>
</GridStyles>
</div>
);
)
<GridStyles>
savingState ? saving ? <p>saving</p> : <p>saved</p> : null
deletingState ? deleting ? <p>deleting</p> : null : null
<button type="submit">Save Form</button>
</GridStyles>
</div>
</FormStyles>
<AddFormStyles onSubmit=handleSubmit2(addInput)>
<div>
<label htmlFor="chooseType">Input Type</label>
<select name="chooseType" ref=register2>
<option value="text">text</option>
<option value="image"> image</option>
</select>
</div>
<button type="submit">Add Form Inputs</button>
</AddFormStyles>
</>
);
【问题讨论】:
网络标签...请求出现?只是没有重新渲染? 当我循环回到页面时,网络选项卡中只有三个不相关的东西 嗯,下一个路由器问题?组件代码重新运行? (console.log(data)
或 formState,或两者兼而有之)...顺便说一句,奇怪的想法...从未使用过空白(只有 3 个加载/错误/数据状态可用/可能在结束/渲染时)...应该在表单内作为默认道具...或有条件地查询输入(当没有 prop 表单 ID 时跳过选项)...if(formData) setFormState(formData)
[或if(data)
] 生效
我控制了数据和 formState,当我向后和第四次导航时它会显示出来,所以不确定为什么内容没有填充。
包含正确的数据?单独渲染Form
,没有Layout
【参考方案1】:
我们证明(参见 cmets)源自 useQuery
的数据已正确记录并传递到 <Form/>
(子组件)。
问题在于没有重新初始化表单状态 [managing/helper] 挂钩 (useForm
)。应该是有效果的解决了:
const register, handleSubmit, errors, reset = useForm( defaultValues: test );
useEffect(() =>
reset(defaultValues: test);
, [formState])
这个钩子在formState
prop 更改时重置表单状态/数据。
【讨论】:
有一点需要注意,要在没有大量重新渲染的情况下工作,我必须使用 [formState] 而不是 [test]。谢谢以上是关于下一个 JS apollo 链接更改清除查询,必须刷新页面才能运行查询的主要内容,如果未能解决你的问题,请参考以下文章
Apollo GraphQL:更改默认标题 INSIDE React 子组件
Apollo 是不是可以在调用 useLazyQuery 后清除数据 obj