client.writeQuery:无法在未安装的组件上执行React状态更新

时间:2020-05-06 13:28:11

标签: javascript reactjs apollo apollo-client

我有使用useApolloClient

的自定义钩子

挂钩

import { gql, useApolloClient, useQuery } from "@apollo/client"
import { useCallback } from "react"

export const modalQuery = gql`
  query GetModal {
    modal @client {
      name
      props
    }
  }
`

const useModal = () => {
  const client = useApolloClient()
  const { data } = useQuery(modalQuery)

  const open = useCallback(
    ({ name, props = {} }: { name: string; props?: any }) => {
      // Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
      client.writeQuery({
        query: modalQuery,
        data: { modal: { name, props } },
      })
    },
    [client]
  )

  const close = useCallback(() => {
    client.writeQuery({
      query: modalQuery,
      data: { modal: null },
    })
  }, [client])

  return {
    modal: data?.modal,
    close,
    open,
  }
}

export default useModal

我在不同路径的两个组件中使用了这个钩子。 我使用open函数将数据写入要缓存的第一个组件,它显示模式和close模式(写入缓存)

然后我转到第二条路线,并卸下第一个组件,当我使用open时,它将在我以useModal代码块显示的第一个组件上显示警告。

第一个组件

import { Box, Button } from "@material-ui/core"
import React from "react"
import { useModal, useProjectsQuery } from "../../app"
import ProjectsList from "../components/projects-list"

const ProjectsView = () => {
  const { data } = useProjectsQuery()
  const { open } = useModal()

  return (
    <Box>
      <Button
        variant="contained"
        size="small"
        color="primary"
        onClick={() => open({ name: "project-form" })}
      >
        Create Project
      </Button>
      <ProjectsList projects={data?.projects} />
    </Box>
  )
}

export default ProjectsView

第二部分

import { Box, Button } from "@material-ui/core"
import React from "react"
import { BoardQuery, useModal } from "../../../app"
import Columns from "./columns"

type Props = {
  boardId: number
  board: BoardQuery["board"]
}

const Board = ({ board, boardId }: Props) => {
  const { open } = useModal()

  return (
    <Box>
      <header>
        <h1>Board: {board?.name}</h1>
        <Button
          variant="contained"
          color="primary"
          onClick={() => {
            open({ props: { boardId }, name: "column-form" })
          }}
        >
          Create Column
        </Button>
      </header>
      <Columns boardId={boardId} />
    </Box>
  )
}

export default Board

模式组件

import { Modal as MuModal } from "@material-ui/core"
import React from "react"
import { useModal } from "../../lib"
import { modalMap } from "./constants"
import { Container } from "./styles"

const Modal = () => {
  const { modal, close } = useModal()
  const ModalComponent = modalMap[modal?.name]

  return (
    <MuModal open={Boolean(ModalComponent)} onClose={() => close()}>
      <Container>
        {ModalComponent && (
          <ModalComponent
            {...modal?.props}
            onClose={() => {
              close()
              if (modal?.props?.onClose) modal?.props?.onClose()
            }}
          />
        )}
      </Container>
    </MuModal>
  )
}

export default Modal

据我了解,useApolloClient不会取消订阅。我该如何解决?

版本:"@apollo/client": "^3.0.0-beta.43"

0 个答案:

没有答案