mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 23:46:58 +00:00
encapsulates button into context
This commit is contained in:
parent
2fc30b9603
commit
783e7969db
@ -1,33 +1,13 @@
|
||||
'use-client';
|
||||
import chatOperations from 'operations/chatOperations';
|
||||
import { useState } from 'react';
|
||||
import GenerateStoryContextProvider, { IGenerateStoryContext } from './GenerateStoryContext';
|
||||
|
||||
export default function GenerateStoryComponent() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [data, setData] = useState();
|
||||
|
||||
const getStory = async () => {
|
||||
setLoading(true);
|
||||
const data = await chatOperations.createStoryAsync();
|
||||
setData(data);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<GenerateStoryContextProvider>
|
||||
{({ story }: IGenerateStoryContext) => {
|
||||
{({ story, loading }: IGenerateStoryContext) => {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-between p-24">
|
||||
<button
|
||||
onClick={getStory}
|
||||
className="mb-10 rounded bg-blue-500 px-4 py-2 font-bold text-white hover:bg-blue-700"
|
||||
>
|
||||
Run A New Story
|
||||
</button>
|
||||
|
||||
{loading ? <div className="mb10">Loading...</div> : null}
|
||||
{JSON.stringify(data)}
|
||||
</main>
|
||||
);
|
||||
}}
|
||||
|
@ -1,23 +1,22 @@
|
||||
'use client';
|
||||
|
||||
import { IStory } from 'operations/chatOperations';
|
||||
import chatOperations, { IStory } from 'operations/chatOperations';
|
||||
import { PropsWithChildren, createContext, useContext, useMemo, useState } from 'react';
|
||||
|
||||
export interface IGenerateStoryContext {
|
||||
story?: IStory;
|
||||
setStory: (story: IStory) => void;
|
||||
images: string[];
|
||||
setImages: (images: string[]) => void;
|
||||
loading: boolean;
|
||||
}
|
||||
|
||||
const GenerateStoryContext = createContext<IGenerateStoryContext>({
|
||||
story: undefined,
|
||||
setStory: () => {},
|
||||
images: [],
|
||||
setImages: () => {}
|
||||
loading: false
|
||||
});
|
||||
|
||||
function GenerateStoryContextProvider({ children }: { children: PropsWithChildren<any> }) {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [story, setStory] = useState<IStory>();
|
||||
/*
|
||||
Note(Benson): For now images is an array of urls where each index in the array
|
||||
@ -27,13 +26,26 @@ function GenerateStoryContextProvider({ children }: { children: PropsWithChildre
|
||||
const [images, setImages] = useState<string[]>([]);
|
||||
|
||||
const value = useMemo<IGenerateStoryContext>(
|
||||
() => ({ story, setStory, images, setImages }),
|
||||
[story, setStory, images, setImages]
|
||||
() => ({ story, images, loading }),
|
||||
[story, images, loading]
|
||||
);
|
||||
|
||||
return (
|
||||
<GenerateStoryContext.Provider value={value}>
|
||||
{typeof children === 'function' ? children(value) : children}
|
||||
<>
|
||||
<button
|
||||
onClick={async () => {
|
||||
setLoading(true);
|
||||
const story = await chatOperations.createStoryAsync();
|
||||
setStory(story);
|
||||
setLoading(false);
|
||||
}}
|
||||
className="mb-10 rounded bg-blue-500 px-4 py-2 font-bold text-white hover:bg-blue-700"
|
||||
>
|
||||
Run A New Story
|
||||
</button>
|
||||
{typeof children === 'function' ? children(value) : children}
|
||||
</>
|
||||
</GenerateStoryContext.Provider>
|
||||
);
|
||||
}
|
||||
|
56
lib/utils/usePromiseMemo.ts
Normal file
56
lib/utils/usePromiseMemo.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import dependenciesMatch from 'utils/dependenciesMatch';
|
||||
|
||||
const usePromiseMemo = <T, E = unknown>(
|
||||
promise: () => Promise<T>,
|
||||
nextDeps: unknown[]
|
||||
): { results?: T; error?: E; loading: boolean; refetch: () => void } => {
|
||||
const [results, setResults] = useState<T>();
|
||||
const [error, setError] = useState<E>();
|
||||
const [hasFinished, setHasFinished] = useState<boolean>(false);
|
||||
const dependencies = useRef<unknown[]>(nextDeps);
|
||||
|
||||
const isMounted = useRef(true);
|
||||
|
||||
const checkIfPromiseIsStillValid = useCallback(
|
||||
(dependenciesAtTimeOfPromise: unknown[]): boolean => {
|
||||
return (
|
||||
isMounted.current && dependenciesMatch(dependenciesAtTimeOfPromise, dependencies.current)
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const run = useCallback(() => {
|
||||
setHasFinished(false);
|
||||
promise()
|
||||
.then((r) => checkIfPromiseIsStillValid(nextDeps) && setResults(r))
|
||||
.catch((e) => checkIfPromiseIsStillValid(nextDeps) && setError(e))
|
||||
.finally(() => checkIfPromiseIsStillValid(nextDeps) && setHasFinished(true));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, nextDeps);
|
||||
|
||||
useEffect(() => {
|
||||
isMounted.current = true;
|
||||
dependencies.current = nextDeps;
|
||||
run();
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
};
|
||||
// nextDeps is already a dependency of run
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [run]);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
results,
|
||||
error,
|
||||
loading: !hasFinished,
|
||||
refetch: run
|
||||
}),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[hasFinished, results]
|
||||
);
|
||||
};
|
||||
|
||||
export default usePromiseMemo;
|
@ -40,9 +40,13 @@ async function createStoryAsync(
|
||||
content: userPrompt
|
||||
}
|
||||
];
|
||||
const data = await post('/api/open-ai/chat', generateRequestPayload(messages));
|
||||
// const data = await post('/api/revalidate', generateRequestPayload(messages));
|
||||
return getFunctionCallArguments<IStory>(data);
|
||||
try {
|
||||
const data = await post('/api/open-ai/chat', generateRequestPayload(messages));
|
||||
return getFunctionCallArguments<IStory>(data);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
export default { createStoryAsync };
|
||||
|
Loading…
x
Reference in New Issue
Block a user