reactjs 如何访问object.id在react,graphql中的更新变异与prisma

w1jd8yoj  于 2022-12-22  发布在  React
关注(0)|答案(2)|浏览(119)
    • bounty将在3天后过期**。回答此问题可获得+100声望奖励。Mel希望引起更多人对此问题的关注:我正在尝试弄清楚如何在react中将对象传递给更新表单

I am trying to figure out how to access the object.id on the update mutation I have made in my app.
我有一个名为IssueGroup的对象。我做了创建和删除的修改,大部分情况下,它们都能正常工作。我被更新的修改卡住了,因为我似乎不能让它识别我试图更新的对象的id。
我有一张表格:

import * as React from "react"
import { gql } from "@apollo/client"
import { 
  Box, 
  Button, 
  Checkbox, 
  Heading, 
  IconButton, 
  useDisclosure, 
  Wrap, 
  List, 
  ListItem, 
  Table,
  Thead,
  Tbody,
  Tfoot,
  Tr,
  Th,
  Td,
  TableCaption,
  TableContainer, 
  Text
} from "@chakra-ui/react"
import Head from "next/head"
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"
import { PartialCheckIcon } from "components/PartialCheckIcon"
import { Search } from "components/Search"
import type { Sort } from "components/Table"

const __ = gql`
  query AllIssueGroups {
    allIssueGroups {
      id 
      title
      description
    }
  }

  

  mutation deleteIssueGroup($id: String!) {
    deleteIssueGroup(id: $id) {
      id
      title
      description
      issues
    }
  }
`

export default function IssueGroups() {
  const toast = useToast()
  const [search, setSearch] = React.useState("")
  const [selectedIssueGroups, setSelectedIssueGroups] = React.useState<string[]>([])
  const modalProps = useDisclosure()
  const modalPropsUpdate = useDisclosure()
  const [sort, setSort] = React.useState<Sort>({ createdAt: SortOrder.Desc })
  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>

     
        
           
            

                <TableContainer maxW="80%">
                  <Table variant='simple'>
                    <Tbody>
                    {data?.allIssueGroups.map((issueGroup) => (
                      <Tr key={issueGroup.id}>
                      
         
                        <Td>
                          <Text textStyle="h6">{issueGroup.title}</Text>
                          <Text textStyle="sm">{issueGroup.description}</Text>

                        </Td>
                        <Td>
                        <IconButton
                              variant='outline'
                              aria-label='update'
                              fontSize='15px'
                              ml={4}
                              icon={<CgEditMarkup />}
                              onClick={modalPropsUpdate.onOpen}
                            
                          />
                          <Modal {...modalPropsUpdate} title="Update Issue Group">
                            <AdminUpdateIssueGroupForm onClose=
{modalPropsUpdate.onClose} />
                              </Modal>
    
                            </Td>
                            <Td> 
                              <IconButton
                                  variant='outline'
                                  aria-label='delete'
                                  fontSize='15px'
                                  ml={4}
                                  icon={<CgTrash />}
                                  onClick={() => onDeleteIssueGroup(issueGroup.id)}
                                 
                              />
                            </Td>
                           
                          </Tr>
                          ))}
                        </Tbody>
                        
                      </Table>
                    </TableContainer>
    
                
    
              
          
          
        </Box>
      )
    }
    
    IssueGroups.getLayout = (page: React.ReactNode) => <AdminLayout>{page}</AdminLayout>

然后,我有一个模态,当点击更新按钮时打开,它有:

import * as React from "react"
import { gql } from "@apollo/client"
import { Button, Stack, Text } from "@chakra-ui/react"
import { useRouter } from "next/router"

import { useAllIssueGroupsQuery, useUpdateIssueGroupMutation, IssueGroupInput } from "lib/graphql"
import { useForm } from "lib/hooks/useForm"
import Yup from "lib/yup"

import { ButtonGroup } from "./ButtonGroup"
import { Form } from "./Form"
import { FormError } from "./FormError"
import { Input } from "./Input"
import { Textarea } from "./Textarea"
import { Modal } from "antd"
import { GiConsoleController } from "react-icons/gi"

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) => {
    // await form.triggerValidation()
    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}/>
       
        <FormError />
        <ButtonGroup>
          <Button onClick={props.onClose}>Cancel</Button>
          <Button
           
             type="submit"
            isLoading={form.formState.isSubmitting}
            isDisabled={form.formState.isSubmitting}
            color="brand.white"
            fontWeight="normal"
            backgroundColor="brand.orange"
            
            _hover={{
              backgroundColor: "brand.green",
              color: "brand.white",
            }}
          >
            Create
          </Button>
        </ButtonGroup>
      </Stack>
    </Form>
  )
}

我的问题组解决程序具有:

@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,
      },
    })
  }

How can I tell the modal form for update what the specific issueGroup.id related to the button clicked to open the modal is?
prisma方案具有:

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)
}
    • 下次尝试**

I have made a further attempt, which tries to give the modal the issueGroup.id with the onClick handler, but I still can't get the form to recognise the id, and this version of this attempt generates an error message I don't know how to break down. It says:
键入"{关闭时:()=〉无效;问题组:忽略〈问题组,"创建于"| "更新时间"| "问题"〉|"null ;}"不能赋给类型"IntrinsicAttributes & Props"。属性"issueGroup"不存在
在类型"IntrinsicAttributes & Props"上。
这一次:

  • 我尝试设置状态:
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()
                                  }}
                                  _hover={{
                                    backgroundColor: "brand.blue",
                                    color: "brand.white",
                                  }}
                              />
                              <Modal {...modalPropsUpdate } title="Update Issue Group">
                                <AdminUpdateIssueGroupForm onClose={modalPropsUpdate.onClose} issueGroup ={selectedIssueGroup}  />
                              </Modal>

Then, in the form, I tried to read issueGroup.id:

import * as React from "react"
import { gql } from "@apollo/client"
import { Button, Stack, Text } from "@chakra-ui/react"
import { useRouter } from "next/router"

import { useAllIssueGroupsQuery, useUpdateIssueGroupMutation, IssueGroupInput } from "lib/graphql"
import { useForm } from "lib/hooks/useForm"
import Yup from "lib/yup"

import { ButtonGroup } from "./ButtonGroup"
import { Form } from "./Form"
import { FormError } from "./FormError"
import { Input } from "./Input"
import { Textarea } from "./Textarea"
import { Modal } from "antd"
import { GiConsoleController } from "react-icons/gi"

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

///我想下面这行代码可能对错误信息有帮助,它确实消除了上面的错误,但它没有解决问题,因为这个页面不知道selectedIssueGroup的意思,所以我想我只是把同样的问题推来推去。

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")
        
        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}/>
       
        <FormError />
        <ButtonGroup>
          <Button onClick={props.onClose}>Cancel</Button>
          <Button
           
             type="submit"
            isLoading={form.formState.isSubmitting}
            isDisabled={form.formState.isSubmitting}
            color="brand.white"
            fontWeight="normal"
            backgroundColor="brand.orange"
            
            _hover={{
              backgroundColor: "brand.green",
              color: "brand.white",
            }}
          >
            Create
          </Button>
        </ButtonGroup>
      </Stack>
    </Form>
  )
}

经过这次尝试,我的窗体仍然不知道selectedIssueGroup或IssueGroup的含义。
我看过react docs的这一页,我想我遗漏了一点,那就是我没有用isActive的等价物 Package 我的表单。问题是,我不知道把selectedIssueGroup放在哪里。我对那个状态的定义在一个与保存表单的文件不同的文件中。
在尝试应用本文档中的逻辑时,我尝试更改模态,以便将 Package 在状态中,如下所示:

{selectedIssueGroup &&
                              <Modal {...modalPropsUpdate } title="Update Issue Group">
                              <AdminUpdateIssueGroupForm onClose={modalPropsUpdate.onClose} issueGroup ={selectedIssueGroup}  />
                              </Modal>
                            }

我没有收到任何新的错误,但它也不起作用。我的窗体仍然不知道issueGroup是什么。
我可以看到update按钮知道issueGroup是什么,而且Modal也知道它,但我不知道如何将该值赋给update表单。

我看过this tutorial,它展示了如何使用创建表单进行编辑。它使用的屏幕截图显示了在编辑表单中填充的创建信息,但它没有显示它是如何在该表单中找到要使用的数据的。我找不到如何做到这一点的示例。

    • 下一次尝试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:

布尔值;打开时:()=〉无效; ...还有四个...获取披露属性:( prop ?:任意)=〉任意; "}"不可分配给类型" IntrinsicAttributes & Props & {children?":类型"IntrinsicAttributes & Props & {children?:"上不存在属性"issueGroup"React节点;}"。
不知道这是什么意思,控制台日志里面更新按钮,模态上面下面都知道issueGroup是什么。
我认为它不是必需的原因是我可以在模态之上和加载表单的模态内部的组件之上记录问题组的值。这两个日志都显示了我想在表单中使用的问题组的值。
我在寻找记录表单组件中issueGroup的值的方法时遇到了麻烦(呈现在Modal中),我尝试按如下方式进行:

const CheckIfModalKnowsIssueGroupId = props => {
  console.log("checking if modal knows the issue group", props.toLog);
  return (
    <div>
      {props.children}
    </div>
  );
};

//如果我尝试将模态上的此检查用作位置#1,我可以看到日志记录了issueGroup

<CheckIfModalKnowsIssueGroupId toLog={selectedIssueGroup}>
<Modal {...modalPropsUpdate } title="Update Issue Group" >

//如果我尝试将其用作位置#2(窗体上方),我可以看到日志记录了issueGroup

<CheckIfModalKnowsIssueGroupId toLog={selectedIssueGroup}>
         <AdminUpdateIssueGroupForm 
           onClose={modalPropsUpdate.onClose} 
           issueGroup ={selectedIssueGroup} 
           >
    </CheckIfModalKnowsIssueGroupId>

//如果我对此进行重构以尝试使CheckIfModalKnowsIssueGroupId成为窗体的子级,则控制台不会记录任何内容{console. log("issueGroup inside modal",selectedIssueGroup)}
替代尝试登录位置#3

<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:布尔值;打开时:()=〉无效;关闭时:()=〉void;打开开关:()=〉无效;受控:布尔值;获取按钮属性:( prop ?:任意)=〉任意;获取披露属性:( prop ?:任意)=〉任意;“}"没有调用签名。
我找不到不产生错误的语法。
这个尝试的目的是查看模态是否是开放的,并且仍然知道selectedIssueGroup是什么。在找到查看isOpen是否为真所需的语法之前,我无法进行检查。

新意见

我看过this repo,它建议应该可以重用create表单来处理更新,并且update函数使用subscription而不是prisma id值,但实际上并没有在表单处理程序中引用它,可能知道如何读取对象id而不显式地提供它。也许这就是订阅所能做的。我找不到一个使用我所采用的结构来允许id与表单通信的示例。

vpfxa7rd

vpfxa7rd1#

从您发布的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变量派生的。

r8uurelv

r8uurelv2#

列表对要使用id的项目上的onClick操作做出React的典型模式是:

list.map(el => (
  <div key={el.id} onclick={() => clickHandler(el.id)>
    ... the rest of your layout
  </div>
)

这里的clickHandler函数是你想要在点击时运行的任何函数。这个函数应该接受对象的id作为参数。如果你正在使用表单,这个函数可以反过来调用表单的提交处理程序。

相关问题