feat(react): update to react 18

This commit is contained in:
Bastian Ike
2022-05-13 12:49:09 +02:00
committed by Bastian
parent f4c5c9edec
commit f28aad8bcb
35 changed files with 27496 additions and 16761 deletions

View File

@@ -5,9 +5,9 @@ import Footer from "./Footer/Footer";
import Router from "./Router";
import {
BrowserRouter,
Switch,
Routes,
Route,
Redirect,
Navigate,
useParams,
useLocation,
} from "react-router-dom";
@@ -15,10 +15,6 @@ import { Item } from "../model";
import { Messages, MessagesProvider } from "../context/MessagesContext";
import { ConfigData } from "../config";
interface Params {
page: string;
}
const useFetch = <D extends unknown>(url: string): D | undefined => {
const [data, setData] = React.useState<D>();
@@ -38,6 +34,10 @@ const useFetch = <D extends unknown>(url: string): D | undefined => {
const useQuery = () => new URLSearchParams(useLocation().search);
const usePage = (params: Record<string, string | undefined>) => {
return (params['*'] || '').replace(".html", "");
};
const RouterWithPageParam = ({
items,
releases,
@@ -47,12 +47,12 @@ const RouterWithPageParam = ({
releases: string[];
config: ConfigData;
}) => {
const { page } = useParams<Params>();
const page = usePage(useParams());
const query = useQuery();
return (
<Router
pageName={page}
pageName={page || ""}
search={query.get("search") || ""}
items={items}
releases={releases}
@@ -62,15 +62,15 @@ const RouterWithPageParam = ({
};
const HeaderWithPageParam = () => {
const { page } = useParams<Params>();
const page = usePage(useParams());
return <Header pageName={page} />;
return <Header pageName={page || ""} />;
};
const FooterWithPageParam = ({ items }: { items: Item[] }) => {
const { page } = useParams<Params>();
const page = usePage(useParams());
return <Footer pageName={page} items={items} />;
return <Footer pageName={page || ""} items={items} />;
};
interface Data {
@@ -83,35 +83,41 @@ export default function App() {
const messages = useFetch<Messages>(
`${process.env.PUBLIC_URL}/messages.json`
);
const config = useFetch<ConfigData>(
`${process.env.PUBLIC_URL}/config.json`
);
const config = useFetch<ConfigData>(`${process.env.PUBLIC_URL}/config.json`);
if (data && config) {
const { items, releases } = data;
return (
<MessagesProvider messages={messages}>
<BrowserRouter basename={`${process.env.PUBLIC_URL}`}>
<Switch>
<Route path={"/:page(.+).html"}>
<div>
<div className="page">
<div className="page__header">
<HeaderWithPageParam />
</div>
<div className={classNames("page__content")}>
<RouterWithPageParam config={config} items={items} releases={releases} />
</div>
<div className="page__footer">
<FooterWithPageParam items={items} />
<Routes>
<Route
path={"/*"}
element={
<div>
<div className="page">
<div className="page__header">
<HeaderWithPageParam />
</div>
<div className={classNames("page__content")}>
<RouterWithPageParam
config={config}
items={items}
releases={releases}
/>
</div>
<div className="page__footer">
<FooterWithPageParam items={items} />
</div>
</div>
</div>
</div>
</Route>
<Route path={"/"}>
<Redirect to={"/index.html"} />
</Route>
</Switch>
}
/>
<Route
path={"/"}
element={<Navigate replace to={"/index.html"} />}
/>
</Routes>
</BrowserRouter>
</MessagesProvider>
);

View File

@@ -5,7 +5,7 @@ import Link from "../Link/Link";
import LogoLink from "../LogoLink/LogoLink";
import Search from "../Search/Search";
import { radarNameShort } from "../../config";
import { useHistory } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import qs from "query-string";
import { useMessages } from "../../context/MessagesContext";
@@ -13,7 +13,7 @@ export default function Header({ pageName }: { pageName: string }) {
const [searchOpen, setSearchOpen] = useState(false);
const [search, setSearch] = useState("");
const { searchLabel, pageHelp, pageOverview } = useMessages();
const history = useHistory();
const navigate = useNavigate();
const searchRef = useRef<HTMLInputElement>(null);
const openSearch = () => {
@@ -29,7 +29,7 @@ export default function Header({ pageName }: { pageName: string }) {
};
const handleSearchSubmit = () => {
history.push({
navigate({
pathname: "/overview.html",
search: qs.stringify({ search: search }),
});
@@ -55,20 +55,20 @@ export default function Header({ pageName }: { pageName: string }) {
<div className="nav__item">
<Link pageName="help-and-about-tech-radar" className="icon-link">
<span className="icon icon--question icon-link__icon" />
{pageHelp.headlinePrefix || 'How to use' } {radarNameShort}?
{pageHelp.headlinePrefix || "How to use"} {radarNameShort}?
</Link>
</div>
)}
<div className="nav__item">
<Link pageName="overview" className="icon-link">
<span className="icon icon--overview icon-link__icon" />
{ pageOverview?.title || 'Technologies Overview' }
{pageOverview?.title || "Technologies Overview"}
</Link>
</div>
<div className="nav__item">
<button className="icon-link" onClick={handleOpenClick}>
<span className="icon icon--search icon-link__icon" />
{ searchLabel || 'Search' }
{searchLabel || "Search"}
</button>
<div className={classNames("nav__search", { "is-open": searchOpen })}>
<Search

View File

@@ -6,7 +6,10 @@ interface Props {
secondary?: boolean;
}
const HeadlineGroup: React.FC<Props> = ({ children, secondary = false }) => (
const HeadlineGroup: React.FC<React.PropsWithChildren<Props>> = ({
children,
secondary = false,
}) => (
<div
className={classNames("headline-group", {
"headline-group--secondary": secondary,

View File

@@ -5,7 +5,10 @@ interface Props {
alt?: string;
}
const HeroHeadline: React.FC<Props> = ({ children, alt }) => (
const HeroHeadline: React.FC<React.PropsWithChildren<Props>> = ({
children,
alt,
}) => (
<div className="hero-headline">
{children} <span className="hero-headline__alt">{alt}</span>
</div>

View File

@@ -8,6 +8,6 @@ describe("Item", () => {
it("Should render the item", () => {
render(<Item item={testItem} />, { wrapper: MemoryRouter });
expect(screen.queryByText(testItem.title)).toBeInTheDocument();
expect(screen.getByText(testItem.title)).toBeInTheDocument();
});
});

View File

@@ -11,7 +11,7 @@ type ItemListProps = {
itemStyle?: React.CSSProperties[];
};
const ItemList: React.FC<ItemListProps> = ({
const ItemList: React.FC<React.PropsWithChildren<ItemListProps>> = ({
children,
items,
activeItem,

View File

@@ -30,7 +30,12 @@ export default function PageQuadrant({
<HeadlineGroup>
<HeroHeadline>{translate(config, pageName)}</HeroHeadline>
</HeadlineGroup>
<QuadrantSection groups={groups} quadrantName={pageName} config={config} big />
<QuadrantSection
groups={groups}
quadrantName={pageName}
config={config}
big
/>
</Fadeable>
);
}

View File

@@ -1,15 +1,12 @@
import { useState, useEffect } from "react";
import PageIndex from "./PageIndex/PageIndex";
import PageOverview from "./PageOverview/PageOverview";
import PageHelp from "./PageHelp/PageHelp";
import PageQuadrant from "./PageQuadrant/PageQuadrant";
import PageItem from "./PageItem/PageItem";
import PageItemMobile from "./PageItemMobile/PageItemMobile";
import {
ConfigData,
getItemPageNames,
isMobileViewport,
} from "../config";
import { ConfigData, getItemPageNames, isMobileViewport } from "../config";
import { Item } from "../model";
type RouterProps = {
@@ -30,7 +27,11 @@ enum page {
notFound,
}
const getPageByName = (items: Item[], pageName: string, config: ConfigData): page => {
const getPageByName = (
items: Item[],
pageName: string,
config: ConfigData
): page => {
if (pageName === "index") {
return page.index;
}
@@ -55,7 +56,7 @@ export default function Router({
items,
releases,
search,
config
config,
}: RouterProps) {
const [statePageName, setStatePageName] = useState(pageName);
const [leaving, setLeaving] = useState(false);
@@ -63,7 +64,8 @@ export default function Router({
useEffect(() => {
const nowLeaving =
getPageByName(items, pageName, config) !== getPageByName(items, statePageName, config);
getPageByName(items, pageName, config) !==
getPageByName(items, statePageName, config);
if (nowLeaving) {
setLeaving(true);
setNextPageName(pageName);

View File

@@ -15,14 +15,14 @@ interface PageHelp {
paragraphs: Paragraph[];
quadrantsPreDescription?: string;
quadrants: Quadrant[];
rings: {name: string, description: string }[];
rings: { name: string; description: string }[];
ringsPreDescription?: string;
sourcecodeLink?: {
href: string;
name: string;
description: string;
};
headlinePrefix?: string
headlinePrefix?: string;
}
interface PageOverview {
@@ -54,10 +54,9 @@ export interface Messages {
const MessagesContext = createContext<Messages | undefined>(undefined);
export const MessagesProvider: FC<{ messages?: Messages }> = ({
messages,
children,
}) => (
export const MessagesProvider: FC<
React.PropsWithChildren<{ messages?: Messages }>
> = ({ messages, children }) => (
<MessagesContext.Provider value={messages}>
{children}
</MessagesContext.Provider>

View File

@@ -1,11 +1,12 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import { createRoot } from "react-dom/client";
import "./index.scss";
ReactDOM.render(
const container = document.getElementById("root")!;
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
</React.StrictMode>
);

View File

@@ -16,5 +16,3 @@ describe("sanitize", () => {
expect(res.__html).toEqual("<a href=\"https://example.org\">Example.org</a>");
});
});