Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 6x 6x 2x 2x 4x 4x 1x 4x 4x 4x 4x 4x 4x 3x 3x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 3x 3x 4x 4x 4x 4x 4x 4x 4x | import { createContext, useContext, useEffect, useState } from 'react';
import { Effect, Stream, Fiber } from 'effect';
import { toast } from 'sonner';
// Services
import { subscribeService } from '@/services/subscription';
// Stores
import { reactionStore } from '@/stores/reaction';
// Types
import { WSReactionData } from '@/types/meal';
// Constants
import { MESSAGES } from '@/constants';
interface ReactionContextValue {
data: WSReactionData;
}
const ReactionContext = createContext<ReactionContextValue | undefined>(
undefined,
);
export const useReaction = () => {
const context = useContext(ReactionContext);
if (!context) {
throw new Error(MESSAGES.OPTION_DATA_CONTEXT_ERROR);
}
return context;
};
export const ReactionProvider = ({
children,
currentOrigin,
}: {
children: React.ReactNode;
currentOrigin?: string;
}) => {
const [data, setData] = useState<WSReactionData>({});
useEffect(() => {
// Run subscription as an Effect fiber
const fiber = Effect.runFork(
Effect.scoped(
subscribeService(currentOrigin).pipe(
Effect.flatMap((stream) =>
stream.pipe(
Stream.tap((reaction) =>
Effect.sync(() => {
if (!reaction) return;
setData((prev) => ({ ...prev, ...reaction }));
const entry = Object.entries(reaction)[0];
if (entry) {
const [id, stats] = entry;
reactionStore.setData(id, stats);
}
}),
),
Stream.runDrain, // consume the stream
),
),
Effect.catchAll((err) => Effect.sync(() => toast.error(err.message))),
),
),
);
// Cleanup: interrupt fiber on unmount
return () => {
Fiber.interrupt(fiber);
};
}, [currentOrigin]);
const contextValue: ReactionContextValue = { data };
return (
<ReactionContext.Provider value={contextValue}>
{children}
</ReactionContext.Provider>
);
};
|