Enonic version: 7.9.2
I have the following part-component:
import React, {useEffect, useState} from 'react';
import {PartProps} from "../../_enonicAdapter/views/BasePart";
import {Box, Grid, Heading} from "@chakra-ui/react";
import {Container} from "@chakra-ui/layout";
import {buildQueryTerms, calculateCursor, pageIndexHelper, parseString} from "../../utils/helpers";
import Pager from "../ui/Pager";
import {useRouter} from "next/router";
import {isArray} from "@chakra-ui/utils";
import GlossaryListFilter from "./GlossaryListFilter";
import {getGlossaryListQuery, IGlossaryListFilter} from "../queries/getGlossaryList";
import {CONTENT_API_URL} from "../../_enonicAdapter/utils";
import {VariablesGetterResult} from "../../_enonicAdapter/ComponentRegistry";
import {GlossaryItem} from "../views/GlossaryItem";
export const GlossaryList = (props: PartProps) => {
const router = useRouter();
const {meta, data, part} = props;
console.log ("Render Mode: ", meta.renderMode);
// Necessary for EDIT-Mode in Content Studio !!
if (!router) {
return <h1>Template Editing Mode ?</h1>
}
const {
term: termFromQuery,
page: pageIndexFromQuery
} = router.query || undefined;
/* todo: extract the following block - also used in MarketNewsArchive */
let pageIndex: number;
if (pageIndexFromQuery === undefined || isArray(pageIndexFromQuery)) {
pageIndex = 1;
} else {
pageIndex = parseInt(pageIndexFromQuery)
}
/*
* some local state
* */
const [glossaryData, setGlossaryData] = useState(data.queryConnection);
const [filter, setFilter] = useState<IGlossaryListFilter>({
term: parseString(termFromQuery)
})
const [isFilterActive, setIsFilterActive] = useState(
termFromQuery !== undefined);
/************************************************************************/
const glossaryList = glossaryData.edges;
const total = glossaryData?.totalCount;
const pageSize = part.config?.first || 10;
const getVars = (): VariablesGetterResult => {
const {page} = router.query;
const offset = calculateCursor({
pageIndex: page ? page : 1,
pageSize: pageSize
});
return {
"path": meta.path,
"query": `type='de.osde.app.be:glossary' and ngram('*','${filter.term}','AND')`,
"offset": offset,
"first": pageSize
}
}
const fetchGlossary = async () => {
const API_URL = CONTENT_API_URL;
let resp;
let total; // total from client fetch
const vars = getVars();
try {
resp = await fetch(API_URL, {
method: 'POST',
body: JSON.stringify({
query: getGlossaryListQuery,
variables: vars
})
});
const filteredGlossary = await resp.json();
total = filteredGlossary.data.guillotine.queryConnection.totalCount;
setGlossaryData(filteredGlossary.data.guillotine.queryConnection);
} catch (e: any) {
console.error("Failed to fetch data %s", e.errorMessage);
}
// todo: also implement for news
const pageHelper = pageIndexHelper({
currentPage: pageIndex,
total: total,
pageSize: pageSize
})
const queryTerms = buildQueryTerms({page: String(pageHelper.page), ...filter});
await router.push(router.query.contentPath + '/?' + queryTerms.toString(),
undefined, {shallow: !pageHelper.shouldChangePage});
}
useEffect(() => {
if (isFilterActive) {
console.log("fetch from client");
fetchGlossary().then(() => {
console.log('fetched from client filter=%s, data=%s', JSON.stringify(filter, null, 2), data)
});
} else {
setGlossaryData(data.queryConnection);
}
}, [filter, data.queryConnection.total, pageIndex]);
return (
<Container maxW={"6xl"}>
<Heading>Outsourcing Glossar</Heading>
<Box>{total} Glossareinträge</Box>
<GlossaryListFilter
filter={filter}
setFilter={setFilter}
setIsActive={setIsFilterActive}
isActive={isFilterActive}/>
{/*todo: make /glossar dynamic*/}
<Pager total={total}
url={'/glossar'}
filter={filter.term}
pageSize={pageSize}
pageIndex={pageIndex}/>
<Grid
gridTemplateColumns={'repeat(auto-fill, minmax(250px, 1fr))'}
columnGap='5'
rowGap={{base: '8', md: '12'}}
my={10}
>
{
glossaryList.map((edge: any, key: number) => <GlossaryItem key={key} {...edge} />)
}
</Grid>
<Pager total={total}
url={'/glossar'}
filter={filter.term}
pageSize={pageSize}
pageIndex={pageIndex}/>
</Container>
);
};
export default GlossaryList;
In the glossary
-component which is called by the glossaryItem
-component I have the following Link, back to this List.
<NextLink href={backLink} passHref>
<Button as={"a"} my={5} colorScheme="brand" variant="outline">
{glossaryData.parent.displayName}
</Button>
</NextLink>
This works as I expected- but when I call the glossary
component directly by its url, I get the following warning. When I call from the link in glossaryItem, this warning does not appear.
Warning: React has detected a change in the order of Hooks called by Header. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks
Previous render Next render
------------------------------------------------------
1. useState useState
2. useContext useContext
3. useContext useContext
4. useState useState
5. useLayoutEffect useLayoutEffect
6. useContext useContext
7. useEffect useEffect
8. useContext useContext
9. useContext useContext
10. useContext useContext
11. undefined useContext
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at Header (webpack-internal:///./src/components/ui/layout/Header.tsx:32:63)
at eval (webpack-internal:///./node_modules/@chakra-ui/toast/dist/chakra-ui-toast.esm.js:465:24)
at EnvironmentProvider (webpack-internal:///./node_modules/@chakra-ui/react-env/dist/chakra-ui-react-env.esm.js:120:24)
at ColorModeProvider (webpack-internal:///./node_modules/@chakra-ui/color-mode/dist/chakra-ui-color-mode.esm.js:194:21)
at ThemeProvider (webpack-internal:///./node_modules/@emotion/react/dist/emotion-element-cbed451f.browser.esm.js:96:64)
at ThemeProvider (webpack-internal:///./node_modules/@chakra-ui/system/dist/chakra-ui-system.esm.js:70:27)
at ChakraProvider (webpack-internal:///./node_modules/@chakra-ui/provider/dist/chakra-ui-provider.esm.js:22:24)
at ChakraProvider (webpack-internal:///./node_modules/@chakra-ui/react/dist/chakra-ui-react.esm.js:253:23)
at MyApp (webpack-internal:///./src/pages/_app.tsx:58:27)
at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/client.js:8:20746)
at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/client.js:8:23395)
at Container (webpack-internal:///./node_modules/next/dist/client/index.js:323:9)
at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:825:26)
at Root (webpack-internal:///./node_modules/next/dist/client/index.js:949:27)
I do not really find this error-stack very helpfull!
Maybe someone had a similar issue and can help!
My first thought was the code at the beginning of the glossaryList
, because this violates the rules for hooks.
// Necessary for EDIT-Mode in Content Studio !!
if (!router) {
return <h1>Template Editing Mode ?</h1>
}
Unfortunately or happily disabling these lines does not help. This only leads in an error in Content-Studio in EDIT-Mode.