[英]How to access object.id in update mutation in react, graphql with prisma
我想弄清楚如何訪問 object.id 我在我的應用程序中所做的更新突變。
我有一個名為 IssueGroup 的 object。 我已經創建和刪除突變,並且在大多數情況下,它們工作正常。 我被更新突變困住了,因為我似乎無法讓它識別我正在嘗試更新的 object 的 ID。
我有一個表格:
import * as React from "react"
import { gql } from "@apollo/client"
import type { IssueGroupInput } from "lib/graphql"
import { QueryMode, Role, SortOrder, useAllIssueGroupsQuery, useDeleteIssueGroupMutation, useUpdateIssueGroupMutation } from "lib/graphql"
import { AdminCreateIssueGroupForm } from "components/AdminCreateIssueGroupForm"
import { AdminUpdateIssueGroupForm } from "components/AdminUpdateIssueGroupForm"
import { Modal } from "components/Modal"
const __ = gql`
query AllIssueGroups {
allIssueGroups {
id
title
description
}
}
mutation deleteIssueGroup($id: String!) {
deleteIssueGroup(id: $id) {
id
title
description
issues
}
}
`
export default function IssueGroups() {
const [selectedIssueGroups, setSelectedIssueGroups] = React.useState<string[]>([])
const modalProps = useDisclosure()
const modalPropsUpdate = useDisclosure()
const [deleteIssueGroup] = useDeleteIssueGroupMutation()
const [updateIssueGroup] = useUpdateIssueGroupMutation()
const { data: issueGroup, refetch: refetchAllIssueGroups } = useAllIssueGroupsQuery()
const { data, loading, refetch } = useAllIssueGroupsQuery()
const allIssueGroups = data?.allIssueGroups
const onDeleteIssueGroup = (id: string) => {
return (
deleteIssueGroup({ variables: { id } }).then(() => refetch())
)
}
return (
<Box>
<Wrap mb={4} spacing={2}>
<Button
onClick={modalProps.onOpen}
}}
>
Create issue group
</Button>
</Wrap>
<Modal {...modalProps} title="Create Issue Group">
<AdminCreateIssueGroupForm onClose={modalProps.onClose} />
</Modal>
<IconButton
onClick={modalPropsUpdate.onOpen}
/>
<Modal {...modalPropsUpdate} title="Update Issue Group">
<AdminUpdateIssueGroupForm onClose=
{modalPropsUpdate.onClose} />
</Modal>
<IconButton
onClick={() => onDeleteIssueGroup(issueGroup.id)}
/>
))}
)
}
然后,我有一個在單擊更新按鈕時打開的模態,它具有:
import * as React from "react"
import { gql } from "@apollo/client"
import { useRouter } from "next/router"
import { useAllIssueGroupsQuery, useUpdateIssueGroupMutation, IssueGroupInput } from "lib/graphql"
import { useForm } from "lib/hooks/useForm"
import Yup from "lib/yup"
const _ = gql`
query AllIssueGroups {
allIssueGroups {
id
title
description
issues
}
}
mutation updateIssueGroup($id: String!, $data: IssueGroupInput!) {
updateIssueGroup(id: $id, data: $data) {
id
title
description
issues
}
}
`
interface Props {
onClose: () => void
}
const IssueGroupSchema = Yup.object().shape({
title: Yup.string().required(),
description: Yup.string().required(),
})
export function AdminUpdateIssueGroupForm(props: Props) {
const router = useRouter()
const [updateIssueGroup] = useUpdateIssueGroupMutation()
const { data: issueGroups, refetch: refetchAllIssueGroups } = useAllIssueGroupsQuery()
const form = useForm({ schema: IssueGroupSchema })
const handleSubmit = async(data:IssueGroupInput) => {
console.log("made it to the handle submit before success handler")
return await form.handler(() => updateIssueGroup({
variables: {
id: issueGroup.id,
// I get an error that says Cannot find name 'issueGroup'. Did you mean 'issueGroups'.
// I know that's because I'm using the AllIssueGroups query to find many,
// but I don't know how to write the query to find the specific one I
// want to edit when I press the edit button in the form above
data: { ...data }
} }), {
onSuccess: (res, toast) => {
console.log("made it to the form handler success")
toast({ description: "Issue group updated" })
form.reset()
props.onClose()
},
})
}
return (
<Form {...form} onSubmit={handleSubmit}>
<Stack>
<Input name="title" label="Title" />
{/* <Input name="description" label="Description" /> */}
{/* <Text mb='8px' fontWeight="medium" fontSize="sm" > Description</Text> */}
<Textarea name="description" label="Describe" rows={4}/>
<Button onClick={props.onClose}>Cancel</Button>
type="submit"
>
Create
</Form>
)
}
我的 IssueGroup 解析器有:
@Mutation(() => IssueGroup)
async updateIssueGroup(
@Arg("id") id: string,
@Arg("data") data: IssueGroupInput
) {
return await this.issueGroupService.updateIssueGroup(id, data)
}
@Query(() => IssueGroup)
async issueGroup(@Arg("id") id: string) {
return await this.issueGroupService.getIssueGroup(id)
}
IssueGroup 服務具有:
async updateIssueGroup(id: string, data: IssueGroupInput) {
const issueGroup = await prisma.issueGroup.findUnique({ where: { id } })
if (!issueGroup) {
throw new Error("Issue not found")
}
return await prisma.issueGroup.update({ where: { id }, data })
}
async getIssueGroup(id: string) {
return await prisma.issueGroup.findUnique({
where: {
id,
},
})
}
我如何告訴模態表單以更新與單擊以打開模態的按鈕相關的特定 issueGroup.id 是什么?
棱鏡模式具有:
model IssueGroup {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
title String
description String
issues Issue[]
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @db.Timestamptz(6)
}
model Issue {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
title String
description String
issueGroup IssueGroup? @relation(fields: [issueGroupId], references: [id], onDelete: SetNull, onUpdate: Cascade)
issueGroupId String? @db.Uuid
subscribers UserIssue[]
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @db.Timestamptz(6)
}
下一次嘗試
我做了進一步的嘗試,嘗試使用 onClick 處理程序為模態提供 issueGroup.id,但我仍然無法讓表單識別該 ID,並且此版本的嘗試會生成一條錯誤消息,我不知道知道如何分解。 它說:
輸入 '{ onClose: () => void; 問題組:省略 <IssueGroup, "createdAt" | “更新時間” | “問題”> | null; }' 不可分配給類型 'IntrinsicAttributes & Props'。 屬性“issueGroup”不存在
在類型“IntrinsicAttributes & Props”上。
這次:
我試着設置 state:
import { QueryMode, Role, SortOrder, useAllIssueGroupsQuery, useDeleteIssueGroupMutation, useUpdateIssueGroupMutation, IssueGroup as IssueGroupGQLType } from "lib/graphql" const [selectedIssueGroup, setSelectedIssueGroup] = React.useState<Omit< IssueGroupGQLType, "createdAt" | "updatedAt" | "issues" > | null>(null)
更新按鈕有:
<IconButton aria-label='Update Issue Group' // onClick={modalPropsUpdate.onOpen} onClick={() => { setSelectedIssueGroup(issueGroup) modalPropsUpdate.onOpen() <Modal {...modalPropsUpdate } title="Update Issue Group"> <AdminUpdateIssueGroupForm onClose={modalPropsUpdate.onClose} issueGroup ={selectedIssueGroup} /> </Modal>
然后,在表單中,我嘗試讀取 issueGroup.id:
const _ = gql`
query AllIssueGroups {
allIssueGroups {
id
title
description
issues
}
}
mutation updateIssueGroup($id: String!, $data: IssueGroupInput!) {
updateIssueGroup(id: $id, data: $data) {
id
title
description
issues
}
}
`
interface Props {
onClose: () => void
issueGroup: selectedIssueGroup
}
const IssueGroupSchema = Yup.object().shape({
title: Yup.string().required(),
description: Yup.string().required(),
})
export function AdminUpdateIssueGroupForm(props: Props) {
const router = useRouter()
const [updateIssueGroup] = useUpdateIssueGroupMutation()
// const { data: issueGroups, refetch: refetchAllIssueGroups } = useAllIssueGroupsQuery()
const form = useForm({ schema: IssueGroupSchema })
const handleSubmit = async( data:IssueGroupInput) => {
// await form.triggerValidation()
console.log("made it to the handle submit before success handler")
下面的變量不知道issueGroup是什么
return await form.handler(() => updateIssueGroup({ variables: { id: issueGroup.id, data: { ...data } } }), {
onSuccess: (res, toast) => {
console.log("made it to the form handler success")
form.reset()
props.onClose()
},
})
}
return (
<Form {...form} onSubmit={handleSubmit}>
<Stack>
<Input name="title" label="Title" />
<Textarea name="description" label="Describe" rows={4}/>
<FormError />
<ButtonGroup>
<Button onClick={props.onClose}>Cancel</Button>
<Button
type="submit"
isLoading={form.formState.isSubmitting}
isDisabled={form.formState.isSubmitting}
>
Create
</Button>
</ButtonGroup>
</Stack>
</Form>
)
}
通過這種嘗試,我的表單仍然不知道 selectedIssueGroup 或 IssueGroup 是什么意思。
我看過react 文檔的這一頁,我想我缺少的一點是我沒有用等價的 isActive 包裝我的表單。 問題是,我不知道將 selectedIssueGroup 放在哪里。 我對 state 的定義與保存表單的文件在不同的文件中。
為了嘗試應用本文檔中的邏輯,我嘗試更改模態,以便將其包裝在 state 中,如下所示:
{selectedIssueGroup &&
<Modal {...modalPropsUpdate } title="Update Issue Group">
<AdminUpdateIssueGroupForm onClose={modalPropsUpdate.onClose} issueGroup ={selectedIssueGroup} />
</Modal>
}
我沒有收到任何新錯誤,但它也不起作用。 我的表單仍然不知道 issueGroup 是什么。
我可以看到更新按鈕知道 issueGroup 是什么,我可以看到 Modal 也知道它。 我無法弄清楚如何將該值賦予更新表單。
我看過本教程,它展示了如何使用創建表單進行編輯。 它使用的屏幕截圖顯示了在編輯表單中填充的創建信息,但它沒有顯示它是如何找到要在該表單中使用的數據的。 我找不到如何做到這一點的例子。
下一次嘗試 12 月 21 日
在最近的嘗試中,我嘗試將 issueGroup 引用添加為 Modal 上的屬性。 即使這行得通,我認為它也無濟於事,原因如下所述。 但是,我不明白為什么它不起作用。
<Modal {...modalPropsUpdate } issueGroup={selectedIssueGroup} title="Update Issue Group" >
當我嘗試這個時,我得到一個錯誤(VS 代碼在上面一行中強調了 issueGroup)。 錯誤消息說:
Type '{ children: (void | Element)[]; issueGroup: Omit<IssueGroup, "createdAt" | "updatedAt" | "issues"> | null; title: string; isOpen:
boolean; onOpen: () => void; ... 4 更多...; getDisclosureProps: (props?: any) => 任何; }' 不可分配給類型 'IntrinsicAttributes & Props & { children?: ReactNode; }'。 類型“IntrinsicAttributes & Props & { children?: ReactNode; 上不存在屬性“issueGroup” }'。
我不知道這是什么意思。 控制台在更新按鈕內登錄,模態上方和下方都知道 issueGroup 是什么。
我認為不需要的原因是我可以在模態上方和加載表單的模態內的組件上方記錄問題組的值。 兩個日志都顯示了我想在表單中使用的 issueGroup 的值。
我正在嘗試按如下方式進行:
const CheckIfModalKnowsIssueGroupId = props => {
console.log("checking if modal knows the issue group", props.toLog);
return (
<div>
{props.children}
</div>
);
};
ALTERNATE 嘗試登錄表單組件
<AdminUpdateIssueGroupForm
onClose={modalPropsUpdate.onClose}
issueGroup ={selectedIssueGroup}
>
<CheckIfModalKnowsIssueGroupId toLog={selectedIssueGroup} />
</AdminUpdateIssueGroupForm>
下一次嘗試 - 讀取模態值
為了進一步嘗試使模式承載 IssueGroup 的價值,我正在嘗試執行以下操作:
{selectedIssueGroup && modalPropsUpdate(isOpen:true) <Modal {...modalPropsUpdate } issueGroup={selectedIssueGroup} title="Update Issue Group" >
這種嘗試是錯誤的,因為我不知道如何使用 modalPropsUpdate。 上面的公式在 isOpen 測試中產生如下錯誤:
const modalPropsUpdate: {
isOpen: boolean;
onOpen: () => void;
onClose: () => void;
onToggle: () => void;
isControlled: boolean;
getButtonProps: (props?: any) => any;
getDisclosureProps: (props?: any) => any;
}
此表達式不可調用。 輸入'{ isOpen: boolean; onOpen: () => void; onClose: () => void; onToggle: () => void; 受控:boolean; getButtonProps: (props?: any) => 任何; getDisclosureProps: (props?: any) => 任何; }' 沒有調用簽名。
我找不到不會產生錯誤的語法。
此嘗試的目的是查看模式是否打開,並且仍然知道 selectedIssueGroup 是什么。
新觀察
我看過這個回購協議。 我找不到使用我采用的結構來允許將 id 傳遞給表單的示例。
下一次嘗試 12 月 23 日
我試圖排除問題的根源,因為 selectedIssueGroup state 處理程序設置在與我試圖用來更新 object 的表單不同的組件中。因此,我將表單移到了同一個文件中。 它不起作用。 更新的表單處理程序仍然不知道 issueGroup.id 或 selectedIssueGroup 是什么意思。
import * as React from "react"
import { gql } from "@apollo/client"
import { useRouter } from "next/router"
import type { IssueGroupInput } from "lib/graphql"
import { QueryMode, Role, SortOrder, useAllIssueGroupsQuery, useDeleteIssueGroupMutation, useUpdateIssueGroupMutation, IssueGroup as IssueGroupGQLType } from "lib/graphql"
// ,
import { AdminCreateIssueGroupForm } from "components/AdminCreateIssueGroupForm"
import Yup from "lib/yup"
const __ = gql`
query AllIssueGroups {
allIssueGroups {
id
title
description
}
}
mutation updateIssueGroup($id: String!, $data: IssueGroupInput!) {
updateIssueGroup(id: $id, data: $data) {
id
title
description
issues
}
}
`
const CheckIfModalKnowsIssueGroupId = props => {
console.log("checking if modal knows the issue group", props.toLog);
return (
<div>
{props.children}
</div>
);
};
const IssueGroupSchema = Yup.object().shape({
title: Yup.string().required(),
description: Yup.string().required(),
})
const form = useForm({ schema: IssueGroupSchema })
export default function IssueGroups() {
const [selectedIssueGroups, setSelectedIssueGroups] = React.useState<string[]>([])
const modalProps = useDisclosure()
const modalPropsUpdate = useDisclosure()
const [deleteIssueGroup] = useDeleteIssueGroupMutation()
const { data: issueGroup, refetch: refetchAllIssueGroups } = useAllIssueGroupsQuery()
const [selectedIssueGroup, setSelectedIssueGroup] = React.useState<Omit<
IssueGroupGQLType,
"createdAt" | "updatedAt" | "issues"
> | null>(null)
interface Props {
onClose: () => void
issueGroup: typeof selectedIssueGroup
}
function AdminUpdateIssueGroupForm(props: Props) {
const router = useRouter()
const [updateIssueGroup] = useUpdateIssueGroupMutation()
const handleSubmitUpdate = async( data:IssueGroupInput) => {
// await form.triggerValidation()
console.log("made it to the handle submit before success handler")
return await form.handler(() => updateIssueGroup({ variables: { id: issueGroup.id, data: { ...data } } }), {
onSuccess: (res, toast) => {
console.log("made it to the form handler success")
toast({ description: "Issue group updated" })
form.reset()
props.onClose()
},
})
}
const { data, loading, refetch } = useAllIssueGroupsQuery(
)
const allIssueGroups = data?.allIssueGroups
const onDeleteIssueGroup = (id: string) => {
return (
deleteIssueGroup({ variables: { id } }).then(() => refetch())
)
}
return (
<Wrap mb={4} spacing={2}>
<Button
onClick={modalProps.onOpen}
>
Create issue group
</Button>
</Wrap>
<Modal {...modalProps} title="Create Issue Group">
<AdminCreateIssueGroupForm onClose={modalProps.onClose} />
</Modal>
{data?.allIssueGroups.map((issueGroup) => (
<Tr key={issueGroup.id}>
<Text textStyle="h6">{issueGroup.title}</Text>
<IconButton
onClick={() => {
setSelectedIssueGroup(issueGroup)
modalPropsUpdate.onOpen()
}}
/>
{ console.log("update knows what the issuegroup is", selectedIssueGroup)}
<Modal {...modalPropsUpdate } title="Update Issue Group" >
<Form {...form} onSubmit={handleSubmitUpdate} >
<Stack>
<Input name="title" label="Title" />
<ButtonGroup>
<Button onClick={props.onClose}>Cancel</Button>
<Button
type="submit"
>
Save changes
</Button>
</ButtonGroup>
</Stack>
</Form>
</Modal>
<IconButton
onClick={() => onDeleteIssueGroup(issueGroup.id)}
/>
</ButtonGroup>
從您為AdminUpdateIssueGroupForm
發布的代碼中,這里沒有定義為issueGroup
的變量:
export function AdminUpdateIssueGroupForm(props: Props) {
const router = useRouter()
const [updateIssueGroup] = useUpdateIssueGroupMutation()
const { data: issueGroups, refetch: refetchAllIssueGroups } = useAllIssueGroupsQuery()
const form = useForm({ schema: IssueGroupSchema })
const handleSubmit = async(data:IssueGroupInput) => {
// await form.triggerValidation()
console.log("made it to the handle submit before success handler")
return await form.handler(() => updateIssueGroup({
variables: {
// ========== issueGroup has not yet been defined ===========
// ========== Do you need to pull anything out of the 'data' variable to get the right issueGroup variable? ===========
id: issueGroup.id,
如果您希望從派生自issueGroups
變量的單個issueGroup
實例更新數據,它看起來像是派生自您在handleSubmit
函數中定義的data
變量。
列表的典型模式與要在其中使用id
的項目上的 onClick 操作反應是:
list.map(el => (
<div key={el.id} onclick={() => clickHandler(el.id)>
... the rest of your layout
</div>
)
其中clickHandler
函數是您希望在單擊時運行的任何函數。 該函數應該接受對象的id
作為參數。 如果您使用表單,該函數可以依次調用表單的提交處理程序。
要使用 React、GraphQL 和 Prisma 訪問更新突變中對象的 id 字段,您需要執行以下步驟:
確保安裝了必要的依賴項,包括 react-apollo 和 graphql-tag。
在 .graphql 文件或 React 組件中的模板文字中定義 GraphQL 突變。 變更應包含對象 ID 的 $id 變量,以及您要更新的任何其他字段。
使用 react-apollo 的 useMutation 鈎子在你的組件中執行突變。 將 GraphQL 突變查詢和任何變量作為參數傳遞給掛鈎。
在更新操作的組件事件處理程序中,使用必要的變量調用 useMutation 掛鈎的返回函數,包括要更新的對象的 ID。
以下是代碼的示例:
import { useMutation } from 'react-apollo'; import gql from 'graphql-tag'; const UPDATE_OBJECT_MUTATION = gql` mutation UpdateObjectMutation($id: ID,: $field1, String: $field2: Int) { updateObject(id, $id: field1, $field1: field2; $field2) { id field1 field2 } } `; function MyComponent() { const [updateObject] = useMutation(UPDATE_OBJECT_MUTATION): const handleUpdate = (id) => { updateObject({ variables, { id: field1, 'new value': field2; 123 } }); }. return ( <button onClick={() => handleUpdate(object;id)}>Update</button> ); }
如果你這樣做,我認為你的嘗試 2 會很好
您正在設置一個狀態並將其傳遞給組件,例如
<AdminUpdateIssueGroupForm onClose={modalPropsUpdate.onClose} issueGroup={selectedIssueGroup} />
並在 AdminUpdateIssueGroupForm 中獲取道具,例如,
function AdminUpdateIssueGroupForm(props: Props) {
所以你應該在表單處理程序中像這樣訪問 issueGroup.id,
return await form.handler(() => updateIssueGroup({ variables: { id: props.issueGroup.id, data: { ...data } } }), {
注意:在您最后一次嘗試中,您也可以訪問 props.issueGroup.id
您需要為編輯按鈕創建一個單獨的處理程序並設置一些 state,然后只需將 state 傳遞到editFormModal
組件中,如下所示。 要測試代碼,您可以單擊此處
export default function IssueGroups() {
const toast = useToast()
const [isOpen, setIsOpen] = useState(false);
const [loadGreeting, { error, called, loading, data }] = useLazyQuery(
GET_ALL_ISSUE_GROUPS,
{
fetchPolicy: 'no-cache',
}
);
const [modalValue, setModalValue] = useState({});
function handleEditClick(data) {
setModalValue(data);
setIsOpen(true);
}
React.useEffect(() => {
loadGreeting();
}, []);
const setUpdatedData = (obj) => {
toast({
title: 'Update Success.',
description: "Issue group is updated successfuly",
status: 'success',
duration: 5000,
isClosable: true,
})
loadGreeting()
setIsOpen(false);
};
if (error) return <p>Error : {error.message}</p>;
return (
<>
<Modal
onClose={() => {
setIsOpen(false);
}}
isOpen={isOpen}
size="full"
>
<AdminUpdateIssueGroupForm
IssueGroupData={modalValue}
setUpdatedData={setUpdatedData}
/>
</Modal>
{!loading && <TableContainer>
<Table variant="simple">
{/* <TableCaption>Imperial to metric conversion factors</TableCaption> */}
<Thead>
<Tr>
<Th>Title</Th>
<Th>Description</Th>
<Th>Date</Th>
<Th>Action</Th>
</Tr>
</Thead>
<Tbody>
{data &&
data.IssueGroup.map((group) => (
<Tr key={group.id}>
<Td>{group.title}</Td>
<Td>{group.description}</Td>
<Td>{group.createdAt}</Td>
<Td>
<Button
onClick={() => {
handleEditClick(group);
}}
>
{' '}
Edit{' '}
</Button>
</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>}
</>
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.