@applicaster/zapp-react-native-utils
Version:
Applicaster Zapp React Native utilities package
66 lines (54 loc) • 1.64 kB
text/typescript
import { create } from "zustand";
import { produce } from "immer";
import { path } from "ramda";
import React from "react";
import { useShallow } from "zustand/react/shallow";
type ScreenState = {
selectedEntry: {
id: string;
};
};
type ScreenId = string;
type GlobalScreenState = Record<ScreenId, ScreenState>;
const screensInitialState: GlobalScreenState = {};
type ScreenStore = {
screens: GlobalScreenState;
setSelectedEntry: (screenId: string, entryId: string) => void;
};
type SetSelectedEntry = (screenId: string, entryId: string) => void;
const useScreenStore = create<ScreenStore>((set) => ({
screens: screensInitialState,
setSelectedEntry: (screenId, entryId) =>
set(
produce((draft) => {
if (!draft.screens[screenId]) {
draft.screens[screenId] = { selectedEntry: { id: "" } };
}
draft.screens[screenId].selectedEntry.id = entryId;
})
),
}));
export function useScreenState(
screenId: ScreenId
): null | { screen: ScreenState; setSelectedEntry: (entryId: string) => void } {
const screenState = useScreenStore<ScreenState>(
useShallow(path(["screens", screenId]))
);
const setSelectedEntry = useScreenStore<SetSelectedEntry>(
useShallow(path(["setSelectedEntry"]))
);
const memoizedSetSelectedEntry = React.useCallback(
(entryId) => setSelectedEntry(screenId, entryId),
[screenId, setSelectedEntry]
);
return React.useMemo(
() =>
!screenId
? null
: {
screen: screenState,
setSelectedEntry: memoizedSetSelectedEntry,
},
[screenId, screenState]
);
}