params in url + error boundary

This commit is contained in:
Primakov Alexandr Alexandrovich 2024-10-24 20:04:54 +03:00
parent c28721b1f4
commit b631206c44
14 changed files with 337 additions and 13 deletions

View File

@ -11,7 +11,7 @@ module.exports = {
navigations: { navigations: {
"nav1.main": "/nav1", "nav1.main": "/nav1",
"link.nav1.about": "/", "link.nav1.about": "/",
"link.nav1.profile": "/my-best-profile-page-ever", "link.nav1.profile": "/my-best-profile-page-ever/:userId/:projectId",
"nav2.main": "/nav2", "nav2.main": "/nav2",
}, },
features: { features: {

221
package-lock.json generated
View File

@ -10,6 +10,8 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@brojs/cli": "^1.3.0", "@brojs/cli": "^1.3.0",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@types/react": "^18.3.12", "@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1", "@types/react-dom": "^18.3.1",
"express": "^4.19.2", "express": "^4.19.2",
@ -1828,6 +1830,167 @@
"webpack-merge": "5.7.2" "webpack-merge": "5.7.2"
} }
}, },
"node_modules/@emotion/babel-plugin": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz",
"integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==",
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/runtime": "^7.18.3",
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/serialize": "^1.2.0",
"babel-plugin-macros": "^3.1.0",
"convert-source-map": "^1.5.0",
"escape-string-regexp": "^4.0.0",
"find-root": "^1.1.0",
"source-map": "^0.5.7",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"license": "MIT"
},
"node_modules/@emotion/babel-plugin/node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@emotion/cache": {
"version": "11.13.1",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz",
"integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==",
"license": "MIT",
"dependencies": {
"@emotion/memoize": "^0.9.0",
"@emotion/sheet": "^1.4.0",
"@emotion/utils": "^1.4.0",
"@emotion/weak-memoize": "^0.4.0",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/hash": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
"integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
"license": "MIT"
},
"node_modules/@emotion/is-prop-valid": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz",
"integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==",
"license": "MIT",
"dependencies": {
"@emotion/memoize": "^0.9.0"
}
},
"node_modules/@emotion/memoize": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
"integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==",
"license": "MIT"
},
"node_modules/@emotion/react": {
"version": "11.13.3",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz",
"integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.12.0",
"@emotion/cache": "^11.13.0",
"@emotion/serialize": "^1.3.1",
"@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
"@emotion/utils": "^1.4.0",
"@emotion/weak-memoize": "^0.4.0",
"hoist-non-react-statics": "^3.3.1"
},
"peerDependencies": {
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/serialize": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz",
"integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==",
"license": "MIT",
"dependencies": {
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/unitless": "^0.10.0",
"@emotion/utils": "^1.4.1",
"csstype": "^3.0.2"
}
},
"node_modules/@emotion/sheet": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
"integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==",
"license": "MIT"
},
"node_modules/@emotion/styled": {
"version": "11.13.0",
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz",
"integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.12.0",
"@emotion/is-prop-valid": "^1.3.0",
"@emotion/serialize": "^1.3.0",
"@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
"@emotion/utils": "^1.4.0"
},
"peerDependencies": {
"@emotion/react": "^11.0.0-rc.0",
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/unitless": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
"integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==",
"license": "MIT"
},
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz",
"integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==",
"license": "MIT",
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@emotion/utils": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz",
"integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==",
"license": "MIT"
},
"node_modules/@emotion/weak-memoize": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
"integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
"license": "MIT"
},
"node_modules/@isaacs/cliui": { "node_modules/@isaacs/cliui": {
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@ -2444,6 +2607,37 @@
"webpack": ">=5" "webpack": ">=5"
} }
}, },
"node_modules/babel-plugin-macros": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5",
"cosmiconfig": "^7.0.0",
"resolve": "^1.19.0"
},
"engines": {
"node": ">=10",
"npm": ">=6"
}
},
"node_modules/babel-plugin-macros/node_modules/cosmiconfig": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
"integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
"license": "MIT",
"dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
"parse-json": "^5.0.0",
"path-type": "^4.0.0",
"yaml": "^1.10.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/babel-plugin-polyfill-corejs2": { "node_modules/babel-plugin-polyfill-corejs2": {
"version": "0.4.11", "version": "0.4.11",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz",
@ -3667,6 +3861,12 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
"license": "MIT"
},
"node_modules/find-up": { "node_modules/find-up": {
"version": "6.3.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
@ -4250,6 +4450,15 @@
"npm": "1.2.8000 || >= 1.4.16" "npm": "1.2.8000 || >= 1.4.16"
} }
}, },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"license": "BSD-3-Clause",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/html-entities": { "node_modules/html-entities": {
"version": "2.5.2", "version": "2.5.2",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz",
@ -5844,6 +6053,12 @@
} }
} }
}, },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
"node_modules/react-router": { "node_modules/react-router": {
"version": "6.27.0", "version": "6.27.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz",
@ -6514,6 +6729,12 @@
"webpack": "^5.27.0" "webpack": "^5.27.0"
} }
}, },
"node_modules/stylis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
"license": "MIT"
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "8.1.1", "version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",

View File

@ -15,6 +15,8 @@
"description": "", "description": "",
"dependencies": { "dependencies": {
"@brojs/cli": "^1.3.0", "@brojs/cli": "^1.3.0",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@types/react": "^18.3.12", "@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1", "@types/react-dom": "^18.3.1",
"express": "^4.19.2", "express": "^4.19.2",

View File

@ -7,8 +7,8 @@ export const URLs = {
profile: { profile: {
isOn: Boolean(getNavigationsValue("link.nav1.profile")), isOn: Boolean(getNavigationsValue("link.nav1.profile")),
url: `${baseUrl}${getNavigationsValue("link.nav1.profile")}`, url: `${baseUrl}${getNavigationsValue("link.nav1.profile")}`,
getUrl() { getUrl(userId: string, projectId: string) {
return this.url; return generatePath(this.url, { userId, projectId });
}, },
}, },
about: { about: {

View File

@ -1,13 +1,16 @@
import React from 'react'; import React from 'react';
import { BrowserRouter, HashRouter } from 'react-router-dom'; import { BrowserRouter, HashRouter } from 'react-router-dom';
import { ThemeProvider } from '@emotion/react'
import { Dashboard } from './dashboard'; import { Dashboard } from './dashboard';
const App = () => { const App = () => {
return ( return (
<BrowserRouter> <ThemeProvider theme={{ colors: { main: 'green' } }}>
<Dashboard /> <BrowserRouter>
</BrowserRouter> <Dashboard />
</BrowserRouter>
</ThemeProvider>
); );
}; };

View File

@ -0,0 +1,24 @@
import React from 'react';
export class ErrorBoundary extends React.Component<{ children: React.ReactNode }, { hasError: boolean }> {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
}
static getDerivedStateFromError(error) {
return {
hasError: true
}
}
render() {
const { hasError } = this.state
return hasError ? <div>Something went wrong</div> : this.props.children;
}
}

View File

@ -3,9 +3,12 @@ import { Routes, Route } from "react-router-dom";
import { URLs } from "./__data__/urls"; import { URLs } from "./__data__/urls";
import { ProfilePage, AboutPage } from "./pages"; import { ProfilePage, AboutPage } from "./pages";
import { ErrorBoundary } from "./components/error-boundary";
const PageWrapper = ({ children }) => ( const PageWrapper = ({ children }) => (
<Suspense fallback={<div>Loading...</div>}>{children}</Suspense> <ErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>{children}</Suspense>
</ErrorBoundary>
); );
export const Dashboard = () => { export const Dashboard = () => {

View File

@ -0,0 +1,18 @@
import styled from '@emotion/styled'
import { Header } from './components'
export const StyledHeader = styled(Header)`
padding-top: 100px;
`;
export const Wrapper = styled.div<{ red?: boolean }>`
max-width: 800px;
margin: 0 auto;
background-color: ${(props) => props.red ? 'red' : props.theme.colors.main};
${StyledHeader.toString()} {
color: palevioletred;
}
`;

View File

@ -3,11 +3,20 @@ import { Link } from "react-router-dom";
import { URLs } from "../../__data__/urls"; import { URLs } from "../../__data__/urls";
import { StyledHeader, Wrapper } from "./about.style";
import { Header } from "./components";
export const AboutPage = () => { export const AboutPage = () => {
return ( return (
<div> <>
<h1>about page</h1> <StyledHeader />
{URLs.profile.isOn && <Link to={URLs.profile.getUrl()}>go to profile page</Link>} <Wrapper>
</div> <StyledHeader />
<Header />
{URLs.profile.isOn && (
<Link to={URLs.profile.getUrl('string-userId', 'string-projectId')}>go to profile page</Link>
)}
</Wrapper>
</>
); );
}; };

View File

@ -0,0 +1,3 @@
import React from "react";
export const Header = ({ className }: { className?: string }) => <h1 className={className}>about page</h1>

View File

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import { Link, useParams } from "react-router-dom";
import { getHistory } from '@brojs/cli' import { getHistory } from '@brojs/cli'
import { getNavigationsValue } from "@brojs/cli"; import { getNavigationsValue } from "@brojs/cli";
@ -13,6 +13,8 @@ export const ProfilePage = () => {
history.push(getNavigationsValue('nav2.main')); history.push(getNavigationsValue('nav2.main'));
} }
const params = useParams<{ userId: string, prodileId: string }>();
return ( return (
<div> <div>
<h1>profile page</h1> <h1>profile page</h1>
@ -21,6 +23,8 @@ export const ProfilePage = () => {
<div> <div>
<a onClick={handletoNav2Click} href={getNavigationsValue('nav2.main')}>edit profile</a> <a onClick={handletoNav2Click} href={getNavigationsValue('nav2.main')}>edit profile</a>
</div> </div>
<pre>{JSON.stringify(params as Required<typeof params>, null, 4)}</pre>
</div> </div>
); );
}; };

28
tags.js Normal file
View File

@ -0,0 +1,28 @@
const makeStyles = (theme) => (body, ...expressions) => {
console.log(body, expressions);
return body.reduce((acc, cur, index) => {
const expression = expressions[index];
if (typeof expression === "function") {
cur += expression(theme);
} else if (expression) {
cur += expression;
}
acc += cur;
return acc;
}, "");
};
let condition = false;
const css = makeStyles({ colors: { main: 'red', notmain: 'green' } })
const styles = css`
width: 100%;
color: ${condition ? "red" : "green"};
background-color: ${(theme) => condition ? theme.colors.main : theme.colors.notmain};
`;
console.log("styles", styles);

9
types/emotion.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
import '@emotion/react'
declare module '@emotion/react' {
export interface Theme {
colors: {
main: string
}
}
}