У меня есть собственный крючок, который использует 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"