기타 NEXTJS SpreadJs SSR렌더링 문제.
추천0 비추천 0
페이지 정보
작성자 바밤바 작성일 2024-02-06 19:27 조회 63회 댓글 0건제품 버전 : 16.1.3
컨트롤 이름 : Spreadjs
본문
관련링크
일단 하려는 일은 data binding입니다. 바인딩을 하기위해서
const workbook: GC.Spread.Sheets.Workbook = designer.getWorkbook();
const sheet = workbook.getActiveSheet();
const source = new GC.Spread.Sheets.Bindings.CellBindingSource(
CALCULATION_WATER_SPRAY_BINDING_DATA_DUMMY,
);
sheet.setDataSource(source);
위와같이 작성 했을때 new GC.Spread.Sheets.Bindings.CellBindingSource 부분에서 문제가 발생합니다.
문제는 페이지 새로고침시에 nextjs에 경우 ssr방식의 랜더링 과정을 거치기때문에 참조를 하지 못해 참조에러가 발생하고 next server에서 500에러를 발생시킵니다.
useEffect(() => {
if (typeof window !== 'undefined') {
const source = new GC.Spread.Sheets.Bindings.CellBindingSource(
CALCULATION_WATER_SPRAY_BINDING_DATA_DUMMY,
);
sheet.setDataSource(source);
}
}, []);
첫번째 해결 방법으로 위처럼 방어로직을 작성 했을때도 같은 오류입니다.
다른 해결방법이 있을까요?
수월하게 검토 하시라고 전체 소스도 첨부합니다.
import ApiActCalculation from "@apis/swagger/ApiActCalculation";
import ApiActRevistion from "@apis/swagger/ApiActRevistion";
import {
Flex,
Select,
Stack,
Button as ChakraBtn,
Image,
Box,
Text,
Tabs,
TabList,
Tab,
} from "@chakra-ui/react";
import Button from "@components/common/Button";
import PageLoading from "@components/common/Loading/PageLoading";
import Header from "@components/common/v2/Layouts/Headers/Header";
import SubHeader from "@components/common/v2/Layouts/Headers/SubHeader";
import Main from "@components/common/v2/Layouts/Main/Main";
import {
CALCULATION_WATER_SPRAY_BINDING_DATA_DUMMY,
CALCULATION_WATER_SPRAY_FIELD_LIST,
} from "@components/common/v2/Spread/fieldList";
import styled from "@emotion/styled";
import { AppState } from "@features/store";
import GC from "@grapecity/spread-sheets";
import dynamic from "next/dynamic";
import { useEffect, useState } from "react";
import { useQuery, useQueryClient } from "react-query";
import { useSelector } from "react-redux";
const SpreadSheet: any = dynamic(
() => {
return import("@components/common/v2/Spread/DefaultDesigner");
},
{
loading: () => <PageLoading />,
ssr: false,
},
);
export default function WaterSprayStorageTank() {
const { pid, uid, name, email } = useSelector(
(state: AppState) => state.USER,
);
const SUB_HEADER_BTN = [
{ name: "Figure #1" },
{ name: "Figure #2" },
{ name: "Figure #3" },
{ name: "Figure #4" },
];
const TAB_LIST = [
{ tabName: "3-FB-8001A/B#1" },
{ tabName: "3-FB-8001A/B#1#2" },
{ tabName: "3-FB-8001A/B#1#3" },
{ tabName: "3-FB-8001A/B#1#4" },
];
const [designer, setDesigner] = useState<any>();
const [marid, setMarid] = useState("");
const [isImportExcel, setIsImportExcel] = useState(0);
const queryClient = useQueryClient();
// // revision 리스트 조회
useQuery(
["Calculation", "revisionList"],
() => ApiActRevistion.getCalculationList(pid, uid),
{
onSuccess(data) {
setMarid(data[0].marid);
},
enabled: !!pid && !!uid,
},
);
//Template 조회.
const { data: templateData, isLoading: templateIsLoading } = useQuery(
["Calculation", "TemplateData"],
() =>
ApiActCalculation.getStorageTemplate({
method: "waterspray",
uid,
}),
{
onSuccess(data: any) {
const workbook: GC.Spread.Sheets.Workbook = designer.getWorkbook();
workbook.fromJSON(JSON.parse(data), {
includeBindingSource: true,
});
onBindingData();
},
enabled: !!designer,
},
);
useEffect(() => {
if (pid) {
queryClient.invalidateQueries("Calculation");
}
// 초기화함으로써 프로젝트 변경시마다 데이터 재호출.
}, [pid, queryClient]);
const onBindingData = () => {
const workbook: GC.Spread.Sheets.Workbook = designer.getWorkbook();
const sheet = workbook.getActiveSheet();
const source = new GC.Spread.Sheets.Bindings.CellBindingSource(
CALCULATION_WATER_SPRAY_BINDING_DATA_DUMMY,
);
// 위 로직 적용 시 브라우저 환경에서만 적용이 가능하다 하지만 nextjs에 경우 서버사이드렌더링 (ssr) 방식으로 랜더링이 이루어지기 때문에
// 사용한다면 새로고침시 오류가 발생한다. 따라서 아래와 같이 적용한다.
sheet.setDataSource(source);
};
const TopRenderer = () => (
<>
<Header title={"Storage Tank"}>
<Stack flexDir={"row"}>
<Select />
<Button text="LOAD" clickEvent={onBindingData} />
<Button text="EXPORT" disabled={true} />
<Button text="EXPORT FOR P&ID" disabled={true} />
<Button text="IMPORT" disabled={true} />
<Button text="CALCULATE" disabled={true} />
<Button text="SAVE" disabled={true} />
<Button text="ISSUE" />
</Stack>
</Header>
<SubHeader>
<Flex
w={"100%"}
h={"100%"}
justifyContent={"flex-end"}
alignItems={"center"}
>
<Stack direction={"row"} spacing={"10px"} h={"100%"} mr={"10px"}>
{SUB_HEADER_BTN.map((item, index) => {
return (
<ChakraBtn
flexDir={"column"}
h={"95%"}
key={item.name + index}
px={"2px"}
py={"2px"}
>
<Image
src="/images/figure_btn.png"
w="20px"
h="20px"
objectFit="cover"
loading="lazy"
/>
<Text mt={"5px"}>{item.name}</Text>
</ChakraBtn>
);
})}
</Stack>
<ChakraBtn
bgColor={"#2956AF"}
_hover={{ bgColor: "#4d6cab" }}
color={"#fff"}
>
TO CALCULATION
</ChakraBtn>
</Flex>
</SubHeader>
</>
);
const MainRenderer = () => (
<Container>
<Tabs h={"8%"}>
<TabList>
{TAB_LIST.map((item, index) => {
return <Tab key={item.tabName + index}>{item.tabName}</Tab>;
})}
</TabList>
</Tabs>
<Box h={"92%"}>
<Stack flexDir={"row"} h={"10%"} spacing={"5px"}>
<ChakraBtn
bgColor={"#2956AF"}
_hover={{ bgColor: "#4d6cab" }}
color={"#fff"}
borderRadius={"10px"}
lineHeight={"30px"}
minW={"150px"}
>
CALCULATION
</ChakraBtn>
<ChakraBtn
bgColor={"#2956AF"}
_hover={{ bgColor: "#4d6cab" }}
color={"#fff"}
borderRadius={"10px"}
lineHeight={"30px"}
minW={"150px"}
>
SAVE
</ChakraBtn>
</Stack>
<Box h={"90%"}>
<SpreadSheet
fieldList={CALCULATION_WATER_SPRAY_FIELD_LIST}
setDesigner={setDesigner}
setIsImportExcel={setIsImportExcel}
/>
{templateIsLoading && <PageLoading />}
</Box>
</Box>
</Container>
);
return (
<Main isSubMenu topChildren={TopRenderer()} mainChildren={MainRenderer()} />
);
}
const Container = styled.main`
font-family: "Inter";
overflow: hidden;
height: 100%;
/* .ribbon {
display: none;
}
.top-panels {
display: none;
}
.gc-statusbar {
display: none;
}
tr {
border-top: 0.3px solid #efefef;
} */
`;
댓글목록
등록된 댓글이 없습니다.