client.writeQuery: невозможно выполнить обновление состояния React для отключенного компонента. - PullRequest
0 голосов
/ 06 мая 2020

У меня есть собственный крючок, который использует useApolloClient

Hook

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 модальный (запись в кеш)

Затем я go на второй маршрут, и первый компонент размонтируется, и когда я используйте 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"

...