Merge pull request #751 from notmd/refactor_swr

use `useSWR` data instead calling `setState`
This commit is contained in:
Keith Stevens
2023-01-16 12:15:23 +09:00
committed by GitHub
5 changed files with 39 additions and 59 deletions
+7 -9
View File
@@ -22,7 +22,7 @@ import {
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { QuestionMarkCircleIcon } from "@heroicons/react/20/solid"; import { QuestionMarkCircleIcon } from "@heroicons/react/20/solid";
import clsx from "clsx"; import clsx from "clsx";
import { useEffect, useReducer } from "react"; import { useReducer } from "react";
import { FiAlertCircle } from "react-icons/fi"; import { FiAlertCircle } from "react-icons/fi";
import { get, post } from "src/lib/api"; import { get, post } from "src/lib/api";
import { Message } from "src/types/Conversation"; import { Message } from "src/types/Conversation";
@@ -100,14 +100,12 @@ export const FlaggableElement = (props: FlaggableElementProps) => {
); );
const [isEditing, setIsEditing] = useBoolean(); const [isEditing, setIsEditing] = useBoolean();
const { data, isLoading } = useSWR("/api/valid_labels", get); useSWR("/api/valid_labels", get, {
useEffect(() => { onSuccess: (data) => {
if (isLoading) { const { valid_labels } = data;
return; updateReport({ type: "load_labels", labels: valid_labels });
} },
const { valid_labels } = data; });
updateReport({ type: "load_labels", labels: valid_labels });
}, [data, isLoading]);
const { trigger } = useSWRMutation("/api/set_label", post, { const { trigger } = useSWRMutation("/api/set_label", post, {
onSuccess: () => { onSuccess: () => {
@@ -1,9 +1,8 @@
import { Box, CircularProgress, Stack, StackProps, Text, TextProps, useColorModeValue } from "@chakra-ui/react"; import { Box, CircularProgress, Stack, StackProps, Text, TextProps, useColorModeValue } from "@chakra-ui/react";
import { boolean } from "boolean";
import { useState } from "react";
import { MessageTableEntry } from "src/components/Messages/MessageTableEntry"; import { MessageTableEntry } from "src/components/Messages/MessageTableEntry";
import { get } from "src/lib/api"; import { get } from "src/lib/api";
import useSWR from "swr"; import { Message } from "src/types/Conversation";
import useSWRImmutable from "swr/immutable";
const MessageHeaderProps: TextProps = { const MessageHeaderProps: TextProps = {
fontSize: "xl", fontSize: "xl",
@@ -21,39 +20,24 @@ const MessageStackProps: StackProps = {
interface MessageWithChildrenProps { interface MessageWithChildrenProps {
id: string; id: string;
depth?: number; depth?: number;
maxDepth?: number; maxDepth: number;
isOnlyChild?: boolean; isOnlyChild?: boolean;
} }
export function MessageWithChildren(props: MessageWithChildrenProps) { export function MessageWithChildren(props: MessageWithChildrenProps) {
const backgroundColor = useColorModeValue("white", "gray.800"); const backgroundColor = useColorModeValue("white", "gray.800");
const childBackgroundColor = useColorModeValue("gray.200", "gray.700"); const childBackgroundColor = useColorModeValue("gray.200", "gray.700");
const { id, depth = 0, maxDepth, isOnlyChild = true } = props;
const { id, depth, maxDepth, isOnlyChild = true } = props; const { isLoading, data: message } = useSWRImmutable<Message>(`/api/messages/${id}`, get);
const { isLoading: isLoadingChildren, data: children = [] } = useSWRImmutable<Message[]>(
`/api/messages/${id}/children`,
get
);
const [message, setMessage] = useState(null); const renderRecursive = depth < maxDepth || depth === 0;
const [children, setChildren] = useState(null); const isFirst = depth === 0;
const isFirstOrOnly = isFirst || !!isOnlyChild;
const { isLoading } = useSWR(id ? `/api/messages/${id}` : null, get, {
onSuccess: (data) => {
setMessage(data);
},
onError: () => {
setMessage(null);
},
});
const { isLoading: isLoadingChildren } = useSWR(id ? `/api/messages/${id}/children` : null, get, {
onSuccess: (data) => {
setChildren(data);
},
onError: () => {
setChildren(null);
},
});
const renderRecursive = maxDepth && ((depth && depth < maxDepth) || !depth);
const isFirst = depth === 0 || !depth;
const isFirstOrOnly = isFirst || boolean(isOnlyChild);
if (isLoading || isLoadingChildren) { if (isLoading || isLoadingChildren) {
return <CircularProgress isIndeterminate />; return <CircularProgress isIndeterminate />;
@@ -73,15 +57,15 @@ export function MessageWithChildren(props: MessageWithChildrenProps) {
</Box> </Box>
</> </>
)} )}
{children && Array.isArray(children) && children.length > 0 ? ( {children.length > 0 &&
renderRecursive ? ( (renderRecursive ? (
<Stack {...MessageStackProps}> <Stack {...MessageStackProps}>
<Box bg={childBackgroundColor} padding="4" borderRadius="xl"> <Box bg={childBackgroundColor} padding="4" borderRadius="xl">
{children.map((item, idx) => ( {children.map((item) => (
<Box flex="1" key={`recursiveMessageWChildren_${idx}`}> <Box flex="1" key={`recursiveMessageWChildren_${item.id}`}>
<MessageWithChildren <MessageWithChildren
id={item.id} id={item.id}
depth={depth ? depth + 1 : 1} depth={depth + 1}
maxDepth={maxDepth} maxDepth={maxDepth}
isOnlyChild={children.length === 1 && isOnlyChild} isOnlyChild={children.length === 1 && isOnlyChild}
/> />
@@ -110,10 +94,7 @@ export function MessageWithChildren(props: MessageWithChildrenProps) {
</Box> </Box>
</Stack> </Stack>
</> </>
) ))}
) : (
<></>
)}
</> </>
); );
} }
+9 -1
View File
@@ -6,6 +6,7 @@ import { SessionProvider } from "next-auth/react";
import { FlagsProvider } from "react-feature-flags"; import { FlagsProvider } from "react-feature-flags";
import { getDefaultLayout, NextPageWithLayout } from "src/components/Layout"; import { getDefaultLayout, NextPageWithLayout } from "src/components/Layout";
import flags from "src/flags"; import flags from "src/flags";
import { SWRConfig, SWRConfiguration } from "swr";
import { Chakra, getServerSideProps } from "../styles/Chakra"; import { Chakra, getServerSideProps } from "../styles/Chakra";
@@ -13,6 +14,11 @@ type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout; Component: NextPageWithLayout;
}; };
const swrConfig: SWRConfiguration = {
revalidateOnFocus: false,
revalidateOnMount: true,
};
function MyApp({ Component, pageProps: { session, cookies, ...pageProps } }: AppPropsWithLayout) { function MyApp({ Component, pageProps: { session, cookies, ...pageProps } }: AppPropsWithLayout) {
const getLayout = Component.getLayout ?? getDefaultLayout; const getLayout = Component.getLayout ?? getDefaultLayout;
const page = getLayout(<Component {...pageProps} />); const page = getLayout(<Component {...pageProps} />);
@@ -20,7 +26,9 @@ function MyApp({ Component, pageProps: { session, cookies, ...pageProps } }: App
return ( return (
<FlagsProvider value={flags}> <FlagsProvider value={flags}>
<Chakra cookies={cookies}> <Chakra cookies={cookies}>
<SessionProvider session={session}>{page}</SessionProvider> <SWRConfig value={swrConfig}>
<SessionProvider session={session}>{page}</SessionProvider>
</SWRConfig>
</Chakra> </Chakra>
</FlagsProvider> </FlagsProvider>
); );
@@ -44,6 +44,7 @@ if (boolean(process.env.DEBUG_LOGIN) || process.env.NODE_ENV === "development")
const user = { const user = {
id: credentials.username, id: credentials.username,
name: credentials.username, name: credentials.username,
role: "admin",
}; };
// save the user to the database // save the user to the database
await prisma.user.upsert({ await prisma.user.upsert({
+4 -12
View File
@@ -1,25 +1,17 @@
import { Box, Text, useColorModeValue } from "@chakra-ui/react"; import { Box, Text, useColorModeValue } from "@chakra-ui/react";
import Head from "next/head"; import Head from "next/head";
import { useState } from "react";
import { getDashboardLayout } from "src/components/Layout"; import { getDashboardLayout } from "src/components/Layout";
import { MessageLoading } from "src/components/Loading/MessageLoading"; import { MessageLoading } from "src/components/Loading/MessageLoading";
import { MessageTableEntry } from "src/components/Messages/MessageTableEntry"; import { MessageTableEntry } from "src/components/Messages/MessageTableEntry";
import { MessageWithChildren } from "src/components/Messages/MessageWithChildren"; import { MessageWithChildren } from "src/components/Messages/MessageWithChildren";
import { get } from "src/lib/api"; import { get } from "src/lib/api";
import useSWR from "swr"; import { Message } from "src/types/Conversation";
import useSWRImmutable from "swr/immutable";
const MessageDetail = ({ id }) => { const MessageDetail = ({ id }: { id: string }) => {
const backgroundColor = useColorModeValue("white", "gray.800"); const backgroundColor = useColorModeValue("white", "gray.800");
const [parent, setParent] = useState(null);
const { isLoading: isLoadingParent } = useSWR(id ? `/api/messages/${id}/parent` : null, get, { const { isLoading: isLoadingParent, data: parent } = useSWRImmutable<Message>(`/api/messages/${id}/parent`, get);
onSuccess: (data) => {
setParent(data);
},
onError: () => {
setParent(null);
},
});
if (isLoadingParent) { if (isLoadingParent) {
return <MessageLoading />; return <MessageLoading />;