Initial commit
This commit is contained in:
commit
c03e10da16
36
.gitignore
vendored
Normal file
36
.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
.vscode/
|
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@ -0,0 +1,4 @@
|
||||
.next/
|
||||
node_modules/
|
||||
.vscode/
|
||||
.github/
|
6
.prettierrc.json
Normal file
6
.prettierrc.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": false
|
||||
}
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# ugra-hackathon_frontend
|
||||
|
||||
Training project to get another members of team used to code style
|
9
components/ExampleComponent.jsx
Normal file
9
components/ExampleComponent.jsx
Normal file
@ -0,0 +1,9 @@
|
||||
import React from "react";
|
||||
|
||||
import styles from "styles/exampleComponent.module.css";
|
||||
|
||||
const ExampleComponent = () => {
|
||||
return <button className={styles.button}>Amazing button!</button>;
|
||||
};
|
||||
|
||||
export default ExampleComponent;
|
11
components/PowerfulComponent/handlers.js
Normal file
11
components/PowerfulComponent/handlers.js
Normal file
@ -0,0 +1,11 @@
|
||||
// Лучше писать документацию на функции, за это будет респект от менторов
|
||||
/**
|
||||
* Increase counter
|
||||
* @param {SetStateAction} setCounter
|
||||
*/
|
||||
const handleCounterClick = (setCounter) => {
|
||||
return () => setCounter((prev) => prev + 1); // Если используем контекст, тогда замыкаем всё, что нужно внутри обработчика
|
||||
};
|
||||
|
||||
// Экспорт лучше делать отдельно, чтобы всегда знать, что мы экспортируем из файла, а что используем внутри (как с public/private методами)
|
||||
export { handleCounterClick };
|
26
components/PowerfulComponent/index.js
Normal file
26
components/PowerfulComponent/index.js
Normal file
@ -0,0 +1,26 @@
|
||||
import React, { useCallback, useContext } from "react";
|
||||
|
||||
import { CounterContext } from "context/counterContext";
|
||||
import { handleCounterClick } from "./handlers"; // Обработчики событий лучше держать в отдельном файле или использовать кастомные хуки
|
||||
|
||||
/**
|
||||
* Complex component with counter with context in it
|
||||
*/
|
||||
const PowerfulComponent = () => {
|
||||
const context = useContext(CounterContext);
|
||||
|
||||
console.log(context);
|
||||
|
||||
const handleClick = useCallback(handleCounterClick(context.setCounter), [
|
||||
context.setCounter,
|
||||
]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{context?.counter}</h1>
|
||||
<button onClick={handleClick}>Increase</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PowerfulComponent;
|
22
context/counterContext.js
Normal file
22
context/counterContext.js
Normal file
@ -0,0 +1,22 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
|
||||
const CounterContext = React.createContext(null);
|
||||
|
||||
const initialContext = 0;
|
||||
|
||||
const CounterProvider = ({ children }) => {
|
||||
const [counter, setCounter] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Тут что-то делать для инициализации контекста
|
||||
setCounter(initialContext); // Например
|
||||
}, []);
|
||||
|
||||
const value = useMemo(() => ({ counter, setCounter }), [counter]); // На самом деле, в случе нашего проекта это мало повлияет на производительность, но в каком-то туториале советовали так делать, поэтому почему бы и нет
|
||||
|
||||
return (
|
||||
<CounterContext.Provider value={value}>{children}</CounterContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export { CounterContext, CounterProvider };
|
21
hooks/counter.js
Normal file
21
hooks/counter.js
Normal file
@ -0,0 +1,21 @@
|
||||
import { useState } from "react";
|
||||
|
||||
// Если функционал можно где-то переиспользовать или если код логики компонента занимает больше 150 строк, стоит разбить его на кастомные хуки и вынести сюда
|
||||
/**
|
||||
* Simple counter hook
|
||||
* @param {number} initialState
|
||||
*/
|
||||
const useCounter = (initialState = 0) => {
|
||||
if (typeof initialState !== "number")
|
||||
throw new Error("Initial counter state must be a number");
|
||||
|
||||
const [counter, setCounter] = useState(initialState);
|
||||
|
||||
const increaseCounter = () => {
|
||||
setCounter((prev) => prev + 1);
|
||||
};
|
||||
|
||||
return { counter, increaseCounter };
|
||||
};
|
||||
|
||||
export { useCounter }
|
8
jsconfig.json
Normal file
8
jsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"baseUrl": "."
|
||||
},
|
||||
"exclude": ["node_modules", ".next"]
|
||||
}
|
2
next-env.d.ts
vendored
Normal file
2
next-env.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
22
package.json
Normal file
22
package.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "ugra-hackathon_frontend",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"format": "prettier --write \"**/*.+(js|jsx|json|css|md)\""
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "10.0.3",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.14.10",
|
||||
"@types/react": "^17.0.0",
|
||||
"prettier": "^2.2.0",
|
||||
"typescript": "^4.1.2"
|
||||
}
|
||||
}
|
15
pages/_app.tsx
Normal file
15
pages/_app.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import React from 'react'
|
||||
|
||||
import "styles/globals.css";
|
||||
import { CounterProvider } from "context/counterContext";
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
return (
|
||||
// Здесь компонент Component оборачиваем провайдеры глобального контекста. Если контекст используется не во всём приложении, а в каком-то определённом компоненте и его дочерних элементах, стоит занести провайдер туда
|
||||
<CounterProvider>
|
||||
<Component {...pageProps} />
|
||||
</CounterProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default MyApp;
|
15
pages/counter.tsx
Normal file
15
pages/counter.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
import { useCounter } from "hooks/counter";
|
||||
|
||||
const Counter = () => {
|
||||
const { counter, increaseCounter } = useCounter();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{counter}</h1>
|
||||
<button onClick={increaseCounter}>+</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Counter
|
17
pages/index.tsx
Normal file
17
pages/index.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
import ExampleComponent from "components/ExampleComponent";
|
||||
import PowerfulComponent from "components/PowerfulComponent";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<ExampleComponent />
|
||||
<PowerfulComponent />
|
||||
<Link href="/counter">
|
||||
<a>Simplifyed counter</a>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
}
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
4
public/vercel.svg
Normal file
4
public/vercel.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
6
styles/exampleComponent.module.css
Normal file
6
styles/exampleComponent.module.css
Normal file
@ -0,0 +1,6 @@
|
||||
/* Благодаря использованию css-modules можно использовать одни и те же названия классов
|
||||
в разных компонентах и ничего нам за это не будет, ибо при сборке к ним добавятся хеши */
|
||||
.button {
|
||||
background-color: red;
|
||||
color: white;
|
||||
}
|
16
styles/globals.css
Normal file
16
styles/globals.css
Normal file
@ -0,0 +1,16 @@
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user