diff --git a/src/components/RelationshipList.tsx b/src/components/RelationshipList.tsx index ced612f..637ad82 100644 --- a/src/components/RelationshipList.tsx +++ b/src/components/RelationshipList.tsx @@ -1,4 +1,5 @@ import { DocumentList } from "@/components/DocumentList"; +import { useDocument } from "@/context/document/DocumentContext"; import { pb } from "@/lib/pocketbase"; import { displayName } from "@/lib/relationships"; import type { @@ -7,12 +8,10 @@ import type { Relationship, RelationshipType, } from "@/lib/types"; -import { useQueryClient } from "@tanstack/react-query"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { Loader } from "./Loader"; import { DocumentRow } from "./documents/DocumentRow"; import { NewRelatedDocumentForm } from "./documents/NewRelatedDocumentForm"; -import { useDocument } from "@/context/document/DocumentContext"; interface RelationshipListProps { root: AnyDocument; @@ -27,99 +26,8 @@ export function RelationshipList({ root, relationshipType, }: RelationshipListProps) { - // const [items, setItems] = useState([]); - // const [relationshipId, setRelationshipId] = useState(null); - const [loading, setLoading] = useState(true); + const [_loading, setLoading] = useState(true); const [error, setError] = useState(null); - // const queryClient = useQueryClient(); - - // useEffect(() => { - // async function fetchItems() { - // const { relationship } = await queryClient.fetchQuery({ - // queryKey: ["relationship", relationshipType, root.id], - // staleTime: 5 * 60 * 1000, // 5 mintues - // queryFn: async () => { - // setLoading(true); - // const relationship: Relationship = await pb - // .collection("relationships") - // .getFirstListItem( - // `primary = "${root.id}" && type = "${relationshipType}"`, - // { - // expand: "secondary", - // }, - // ); - // - // setLoading(false); - // - // return { relationship }; - // }, - // }); - // setRelationshipId(relationship.id); - // setItems(relationship.expand?.secondary ?? []); - // } - // - // fetchItems(); - // }, [root, relationshipType]); - - // Handles creation of a new document and adds it to the relationship - // const handleCreate = async (doc: AnyDocument) => { - // setLoading(true); - // setError(null); - // try { - // // Check for existing relationship - // if (relationshipId) { - // console.debug("Adding to existing relationship", relationshipId); - // await pb.collection("relationships").update(relationshipId, { - // "+secondary": doc.id, - // }); - // } else { - // console.debug("Creating new relationship"); - // const relationship = await pb.collection("relationships").create({ - // primary: root.id, - // secondary: [doc.id], - // type: relationshipType, - // }); - // setRelationshipId(relationship.id); - // } - // queryClient.invalidateQueries({ - // queryKey: ["relationship", relationshipType, root.id], - // }); - // setItems((prev) => [doc, ...prev]); - // } catch (e: any) { - // setError(e?.message || "Failed to add document to relationship."); - // } finally { - // setLoading(false); - // } - // }; - // - // const handleRemove = async (documentId: DocumentId) => { - // setLoading(true); - // setError(null); - // - // try { - // if (relationshipId) { - // console.debug("Removing from existing relationship", relationshipId); - // await pb.collection("relationships").update(relationshipId, { - // "secondary-": documentId, - // }); - // } - // queryClient.invalidateQueries({ - // queryKey: ["relationship", relationshipType, root.id], - // }); - // setItems((prev) => prev.filter((item) => item.id != documentId)); - // } catch (e: any) { - // setError( - // e?.message || `Failed to remove document from ${relationshipType}.`, - // ); - // } finally { - // setLoading(false); - // } - // }; - // - // if (loading) { - // ; - // } - const { state, dispatch } = useDocument(); if (state.status === "loading") { @@ -162,10 +70,6 @@ export function RelationshipList({ relationship: updatedRelationship, }); } - dispatch({ - type: "setRelatedDocument", - doc, - }); } catch (e: any) { setError(e?.message || "Failed to add document to relationship."); } finally { diff --git a/src/components/documents/location/LocationEditForm.tsx b/src/components/documents/location/LocationEditForm.tsx index 17f283f..242bbb3 100644 --- a/src/components/documents/location/LocationEditForm.tsx +++ b/src/components/documents/location/LocationEditForm.tsx @@ -1,27 +1,31 @@ import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; import { pb } from "@/lib/pocketbase"; import type { Location } from "@/lib/types"; +import { useDocument } from "@/context/document/DocumentContext"; /** * Renders an editable location form */ export const LocationEditForm = ({ location }: { location: Location }) => { + const { dispatch } = useDocument(); async function saveLocationName(name: string) { - await pb.collection("documents").update(location.id, { + const updated: Location = await pb.collection("documents").update(location.id, { data: { ...location.data, name, }, }); + dispatch({ type: "setDocument", doc: updated }); } async function saveLocationDescription(description: string) { - await pb.collection("documents").update(location.id, { + const updated: Location = await pb.collection("documents").update(location.id, { data: { ...location.data, description, }, }); + dispatch({ type: "setDocument", doc: updated }); } return ( diff --git a/src/components/documents/location/NewLocationForm.tsx b/src/components/documents/location/NewLocationForm.tsx index d6c1f6d..72873c3 100644 --- a/src/components/documents/location/NewLocationForm.tsx +++ b/src/components/documents/location/NewLocationForm.tsx @@ -4,6 +4,7 @@ import { pb } from "@/lib/pocketbase"; import { BaseForm } from "@/components/form/BaseForm"; import { MultiLineInput } from "@/components/form/MultiLineInput"; import { SingleLineInput } from "@/components/form/SingleLineInput"; +import { useDocument } from "@/context/document/DocumentContext"; /** * Renders a form to add a new location. Calls onCreate with the new location document. @@ -15,6 +16,7 @@ export const NewLocationForm = ({ campaign: CampaignId; onCreate: (location: Location) => Promise; }) => { + const { dispatch } = useDocument(); const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [adding, setAdding] = useState(false); @@ -36,6 +38,7 @@ export const NewLocationForm = ({ }); setName(""); setDescription(""); + dispatch({ type: "setDocument", doc: locationDoc}); await onCreate(locationDoc); } catch (e: any) { setError(e?.message || "Failed to add location."); diff --git a/src/components/documents/monsters/MonsterEditForm.tsx b/src/components/documents/monsters/MonsterEditForm.tsx index 258e352..ed17efa 100644 --- a/src/components/documents/monsters/MonsterEditForm.tsx +++ b/src/components/documents/monsters/MonsterEditForm.tsx @@ -1,18 +1,21 @@ import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; import { pb } from "@/lib/pocketbase"; import type { Monster } from "@/lib/types"; +import { useDocument } from "@/context/document/DocumentContext"; /** * Renders an editable monster row */ export const MonsterEditForm = ({ monster }: { monster: Monster }) => { + const { dispatch } = useDocument(); async function saveMonsterName(name: string) { - await pb.collection("documents").update(monster.id, { + const updated = await pb.collection("documents").update(monster.id, { data: { ...monster.data, name, }, }); + dispatch({ type: "setDocument", doc: updated }); } return ( diff --git a/src/components/documents/monsters/NewMonsterForm.tsx b/src/components/documents/monsters/NewMonsterForm.tsx index 09a638f..4c1947e 100644 --- a/src/components/documents/monsters/NewMonsterForm.tsx +++ b/src/components/documents/monsters/NewMonsterForm.tsx @@ -3,6 +3,7 @@ import type { CampaignId, Monster } from "@/lib/types"; import { pb } from "@/lib/pocketbase"; import { BaseForm } from "@/components/form/BaseForm"; import { SingleLineInput } from "@/components/form/SingleLineInput"; +import { useDocument } from "@/context/document/DocumentContext"; /** * Renders a form to add a new monster. Calls onCreate with the new monster document. @@ -14,6 +15,7 @@ export const NewMonsterForm = ({ campaign: CampaignId; onCreate: (monster: Monster) => Promise; }) => { + const { dispatch } = useDocument(); const [name, setName] = useState(""); const [adding, setAdding] = useState(false); const [error, setError] = useState(null); @@ -32,6 +34,7 @@ export const NewMonsterForm = ({ }, }); setName(""); + dispatch({ type: "setDocument", doc: monsterDoc }); await onCreate(monsterDoc); } catch (e: any) { setError(e?.message || "Failed to add monster."); diff --git a/src/components/documents/npc/NewNpcForm.tsx b/src/components/documents/npc/NewNpcForm.tsx index fa934f5..5ffc3ae 100644 --- a/src/components/documents/npc/NewNpcForm.tsx +++ b/src/components/documents/npc/NewNpcForm.tsx @@ -4,6 +4,7 @@ import { pb } from "@/lib/pocketbase"; import { BaseForm } from "@/components/form/BaseForm"; import { SingleLineInput } from "@/components/form/SingleLineInput"; import { MultiLineInput } from "@/components/form/MultiLineInput"; +import { useDocument } from "@/context/document/DocumentContext"; /** * Renders a form to add a new npc. Calls onCreate with the new npc document. @@ -15,6 +16,7 @@ export const NewNpcForm = ({ campaign: CampaignId; onCreate: (npc: Npc) => Promise; }) => { + const { dispatch } = useDocument(); const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [adding, setAdding] = useState(false); @@ -36,6 +38,7 @@ export const NewNpcForm = ({ }); setName(""); setDescription(""); + dispatch({ type: "setDocument", doc: npcDoc }); await onCreate(npcDoc); } catch (e: any) { setError(e?.message || "Failed to add npc."); diff --git a/src/components/documents/npc/NpcEditForm.tsx b/src/components/documents/npc/NpcEditForm.tsx index 0a4ad36..e49221b 100644 --- a/src/components/documents/npc/NpcEditForm.tsx +++ b/src/components/documents/npc/NpcEditForm.tsx @@ -1,4 +1,5 @@ import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; +import { useDocument } from "@/context/document/DocumentContext"; import { pb } from "@/lib/pocketbase"; import type { Npc } from "@/lib/types"; @@ -6,22 +7,25 @@ import type { Npc } from "@/lib/types"; * Renders an editable npc form */ export const NpcEditForm = ({ npc }: { npc: Npc }) => { + const { dispatch } = useDocument(); async function saveNpcName(name: string) { - await pb.collection("documents").update(npc.id, { + const updated: Npc = await pb.collection("documents").update(npc.id, { data: { ...npc.data, name, }, }); + dispatch({ type: "setDocument", doc: updated }); } async function saveNpcDescription(description: string) { - await pb.collection("documents").update(npc.id, { + const updated: Npc = await pb.collection("documents").update(npc.id, { data: { ...npc.data, description, }, }); + dispatch({ type: "setDocument", doc: updated }); } return ( diff --git a/src/components/documents/scene/NewSceneForm.tsx b/src/components/documents/scene/NewSceneForm.tsx index fac2506..b983480 100644 --- a/src/components/documents/scene/NewSceneForm.tsx +++ b/src/components/documents/scene/NewSceneForm.tsx @@ -5,6 +5,7 @@ import type { CampaignId, Scene } from "@/lib/types"; import { pb } from "@/lib/pocketbase"; import { BaseForm } from "@/components/form/BaseForm"; import { MultiLineInput } from "@/components/form/MultiLineInput"; +import { useDocument } from "@/context/document/DocumentContext"; /** * Renders a form to add a new scene. Calls onCreate with the new scene document. @@ -16,6 +17,7 @@ export const NewSceneForm = ({ campaign: CampaignId; onCreate: (scene: Scene) => Promise; }) => { + const { dispatch } = useDocument(); const [text, setText] = useState(""); const [adding, setAdding] = useState(false); const [error, setError] = useState(null); @@ -34,6 +36,7 @@ export const NewSceneForm = ({ }, }); setText(""); + dispatch({ type: "setDocument", doc: sceneDoc }); await onCreate(sceneDoc); } catch (e: any) { setError(e?.message || "Failed to add scene."); diff --git a/src/components/documents/scene/SceneEditForm.tsx b/src/components/documents/scene/SceneEditForm.tsx index 7a9db30..0f03cf2 100644 --- a/src/components/documents/scene/SceneEditForm.tsx +++ b/src/components/documents/scene/SceneEditForm.tsx @@ -1,24 +1,24 @@ import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; import { pb } from "@/lib/pocketbase"; import type { Scene } from "@/lib/types"; +import { useDocument } from "@/context/document/DocumentContext"; import { useQueryClient } from "@tanstack/react-query"; /** * Renders an editable scene form */ export const SceneEditForm = ({ scene }: { scene: Scene }) => { + const { dispatch } = useDocument(); const queryClient = useQueryClient(); async function saveScene(text: string) { - await pb.collection("documents").update(scene.id, { + const updated: Scene = await pb.collection("documents").update(scene.id, { data: { ...scene.data, text, }, }); - queryClient.invalidateQueries({ - queryKey: ["relationship"], - }); + dispatch({ type: "setDocument", doc: updated }); } return ( diff --git a/src/components/documents/secret/NewSecretForm.tsx b/src/components/documents/secret/NewSecretForm.tsx index e56ccdb..ccba454 100644 --- a/src/components/documents/secret/NewSecretForm.tsx +++ b/src/components/documents/secret/NewSecretForm.tsx @@ -5,6 +5,7 @@ import type { CampaignId, Secret } from "@/lib/types"; import { pb } from "@/lib/pocketbase"; import { BaseForm } from "@/components/form/BaseForm"; import { SingleLineInput } from "@/components/form/SingleLineInput"; +import { useDocument } from "@/context/document/DocumentContext"; /** * Renders a form to add a new secret. Calls onCreate with the new secret document. @@ -16,6 +17,7 @@ export const NewSecretForm = ({ campaign: CampaignId; onCreate: (secret: Secret) => Promise; }) => { + const { dispatch } = useDocument(); const [newSecret, setNewSecret] = useState(""); const [adding, setAdding] = useState(false); const [error, setError] = useState(null); @@ -35,6 +37,7 @@ export const NewSecretForm = ({ }, }); setNewSecret(""); + dispatch({ type: "setDocument", doc: secretDoc as Secret}); await onCreate(secretDoc); } catch (e: any) { setError(e?.message || "Failed to add secret."); diff --git a/src/components/documents/secret/SecretEditForm.tsx b/src/components/documents/secret/SecretEditForm.tsx index 6cf837b..8d9adee 100644 --- a/src/components/documents/secret/SecretEditForm.tsx +++ b/src/components/documents/secret/SecretEditForm.tsx @@ -1,20 +1,16 @@ // Displays a single secret with discovered checkbox and text. -import type { Secret, Session } from "@/lib/types"; -import { pb } from "@/lib/pocketbase"; -import { useState } from "react"; import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; +import { useDocument } from "@/context/document/DocumentContext"; +import { pb } from "@/lib/pocketbase"; +import type { Secret } from "@/lib/types"; +import { useState } from "react"; /** * Renders an editable secret form. * Handles updating the discovered state and discoveredIn relationship. */ -export const SecretEditForm = ({ - secret, - session, -}: { - secret: Secret; - session?: Session; -}) => { +export const SecretEditForm = ({ secret }: { secret: Secret }) => { + const { dispatch } = useDocument(); const [checked, setChecked] = useState( !!(secret.data as any)?.secret?.discovered, ); @@ -25,43 +21,28 @@ export const SecretEditForm = ({ setLoading(true); setChecked(newChecked); try { - await pb.collection("documents").update(secret.id, { - data: { - ...secret.data, - discovered: newChecked, - }, - }); - if (session || !newChecked) { - // If the session exists or the element is being unchecked, remove any - // existing discoveredIn relationship - const rels = await pb.collection("relationships").getList(1, 1, { - filter: `primary = "${secret.id}" && type = "discoveredIn"`, + const updated: Secret = await pb + .collection("documents") + .update(secret.id, { + data: { + ...secret.data, + discovered: newChecked, + }, }); - if (rels.items.length > 0) { - await pb.collection("relationships").delete(rels.items[0].id); - } - } - if (session) { - if (newChecked) { - await pb.collection("relationships").create({ - primary: secret.id, - secondary: [session.id], - type: "discoveredIn", - }); - } - } + dispatch({ type: "setDocument", doc: updated }); } finally { setLoading(false); } } async function saveText(text: string) { - await pb.collection("documents").update(secret.id, { + const updated: Secret = await pb.collection("documents").update(secret.id, { data: { ...secret.data, text, }, }); + dispatch({ type: "setDocument", doc: updated }); } return ( diff --git a/src/components/documents/session/SessionEditForm.tsx b/src/components/documents/session/SessionEditForm.tsx index ff19809..8dd44d7 100644 --- a/src/components/documents/session/SessionEditForm.tsx +++ b/src/components/documents/session/SessionEditForm.tsx @@ -1,17 +1,22 @@ import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; +import { useDocument } from "@/context/document/DocumentContext"; import { pb } from "@/lib/pocketbase"; import type { Session } from "@/lib/types"; export const SessionEditForm = ({ session }: { session: Session }) => { + const { dispatch } = useDocument(); + async function saveStrongStart(strongStart: string) { - const freshRecord: Session = await pb - .collection("documents") - .update(session.id, { - data: { - ...session.data, - strongStart, - }, - }); + const doc: Session = await pb.collection("documents").update(session.id, { + data: { + ...session.data, + strongStart, + }, + }); + dispatch({ + type: "setDocument", + doc, + }); } return ( diff --git a/src/components/documents/treasure/NewTreasureForm.tsx b/src/components/documents/treasure/NewTreasureForm.tsx index 28bf60b..19fd650 100644 --- a/src/components/documents/treasure/NewTreasureForm.tsx +++ b/src/components/documents/treasure/NewTreasureForm.tsx @@ -5,6 +5,7 @@ import type { CampaignId, Treasure } from "@/lib/types"; import { pb } from "@/lib/pocketbase"; import { BaseForm } from "@/components/form/BaseForm"; import { SingleLineInput } from "@/components/form/SingleLineInput"; +import { useDocument } from "@/context/document/DocumentContext"; /** * Renders a form to add a new treasure. Calls onCreate with the new treasure document. @@ -16,6 +17,7 @@ export const NewTreasureForm = ({ campaign: CampaignId; onCreate: (treasure: Treasure) => Promise; }) => { + const { dispatch } = useDocument(); const [newTreasure, setNewTreasure] = useState(""); const [adding, setAdding] = useState(false); const [error, setError] = useState(null); @@ -35,6 +37,10 @@ export const NewTreasureForm = ({ }, }); setNewTreasure(""); + dispatch({ + type: "setDocument", + doc: treasureDoc, + }); await onCreate(treasureDoc); } catch (e: any) { setError(e?.message || "Failed to add treasure."); diff --git a/src/components/documents/treasure/TreasureEditForm.tsx b/src/components/documents/treasure/TreasureEditForm.tsx index 5140345..340afb5 100644 --- a/src/components/documents/treasure/TreasureEditForm.tsx +++ b/src/components/documents/treasure/TreasureEditForm.tsx @@ -1,20 +1,16 @@ // Displays a single treasure with discovered checkbox and text. -import type { Treasure, Session } from "@/lib/types"; -import { pb } from "@/lib/pocketbase"; -import { useState } from "react"; import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; +import { useDocument } from "@/context/document/DocumentContext"; +import { pb } from "@/lib/pocketbase"; +import type { Treasure } from "@/lib/types"; +import { useState } from "react"; /** * Renders an editable treasure form. * Handles updating the discovered state and discoveredIn relationship. */ -export const TreasureEditForm = ({ - treasure, - session, -}: { - treasure: Treasure; - session?: Session; -}) => { +export const TreasureEditForm = ({ treasure }: { treasure: Treasure }) => { + const { dispatch } = useDocument(); const [checked, setChecked] = useState( !!(treasure.data as any)?.treasure?.discovered, ); @@ -25,46 +21,33 @@ export const TreasureEditForm = ({ setLoading(true); setChecked(newChecked); try { - await pb.collection("documents").update(treasure.id, { - data: { - ...treasure.data, - treasure: { - ...(treasure.data as any).treasure, - discovered: newChecked, + const updated: Treasure = await pb + .collection("documents") + .update(treasure.id, { + data: { + ...treasure.data, + treasure: { + ...(treasure.data as any).treasure, + discovered: newChecked, + }, }, - }, - }); - if (session || !newChecked) { - // If the session exists or the element is being unchecked, remove any - // existing discoveredIn relationship - const rels = await pb.collection("relationships").getList(1, 1, { - filter: `primary = "${treasure.id}" && type = "discoveredIn"`, }); - if (rels.items.length > 0) { - await pb.collection("relationships").delete(rels.items[0].id); - } - } - if (session) { - if (newChecked) { - await pb.collection("relationships").create({ - primary: treasure.id, - secondary: [session.id], - type: "discoveredIn", - }); - } - } + dispatch({ type: "setDocument", doc: updated }); } finally { setLoading(false); } } async function saveText(text: string) { - await pb.collection("documents").update(treasure.id, { - data: { - ...treasure.data, - text, - }, - }); + const updated: Treasure = await pb + .collection("documents") + .update(treasure.id, { + data: { + ...treasure.data, + text, + }, + }); + dispatch({ type: "setDocument", doc: updated }); } return ( diff --git a/src/context/document/DocumentContext.tsx b/src/context/document/DocumentContext.tsx index 18f89fd..087f353 100644 --- a/src/context/document/DocumentContext.tsx +++ b/src/context/document/DocumentContext.tsx @@ -1,12 +1,11 @@ import { pb } from "@/lib/pocketbase"; import { type AnyDocument, type DocumentId } from "@/lib/types"; +import type { RecordModel } from "pocketbase"; import type { ReactNode } from "react"; import { createContext, useContext, useEffect, useReducer } from "react"; import type { DocumentAction } from "./actions"; import { reducer } from "./reducer"; import { loading, type DocumentState } from "./state"; -import { useQueryClient } from "@tanstack/react-query"; -import type { RecordModel } from "pocketbase"; type DocumentContextValue = { state: DocumentState; @@ -27,20 +26,16 @@ export function DocumentProvider({ documentId: DocumentId; children: ReactNode; }) { - const queryClient = useQueryClient(); const [state, dispatch] = useReducer(reducer, loading()); useEffect(() => { async function fetchDocumentAndRelations() { - const doc: AnyDocument = await queryClient.fetchQuery({ - queryKey: ["document", documentId], - staleTime: 5 * 60 * 1000, // 5 mintues - queryFn: () => - pb.collection("documents").getOne(documentId, { - expand: - "relationships_via_primary,relationships_via_primary.secondary", - }), - }); + const doc: AnyDocument = await pb + .collection("documents") + .getOne(documentId, { + expand: + "relationships_via_primary,relationships_via_primary.secondary", + }); dispatch({ type: "ready", diff --git a/src/context/document/actions.ts b/src/context/document/actions.ts index 650144a..fe5ebbf 100644 --- a/src/context/document/actions.ts +++ b/src/context/document/actions.ts @@ -11,14 +11,10 @@ export type DocumentAction = relatedDocuments: AnyDocument[]; } | { - type: "update"; - data: D["data"]; + type: "setDocument"; + doc: AnyDocument; } | { type: "setRelationship"; relationship: Relationship; - } - | { - type: "setRelatedDocument"; - doc: AnyDocument; }; diff --git a/src/context/document/reducer.ts b/src/context/document/reducer.ts index 3e3022b..d705aca 100644 --- a/src/context/document/reducer.ts +++ b/src/context/document/reducer.ts @@ -3,7 +3,6 @@ import type { AnyDocument, DocumentId, Relationship, - RelationshipId, RelationshipType, } from "@/lib/types"; import type { DocumentAction } from "./actions"; @@ -43,18 +42,23 @@ export function reducer( >, }; - case "update": - if (state.status === "ready") { + case "setDocument": + return ifStatus("ready", state, (state) => { + if (state.doc.id === action.doc.id) { + return { + ...state, + doc: action.doc as D, + }; + } + return { ...state, - doc: { - ...state.doc, - data: action.data, + relatedDocs: { + ...state.relatedDocs, + [action.doc.id]: action.doc, }, }; - } else { - return state; - } + }); case "setRelationship": return ifStatus("ready", state, (state) => ({ ...state, @@ -63,13 +67,5 @@ export function reducer( [action.relationship.type]: action.relationship, }, })); - case "setRelatedDocument": - return ifStatus("ready", state, (state) => ({ - ...state, - relatedDocs: { - ...state.relatedDocs, - [action.doc.id]: action.doc, - }, - })); } }