Added some code styling tips and examples
This commit is contained in:
parent
c0cb43a4c5
commit
1b3fc394c1
2
.gitignore
vendored
2
.gitignore
vendored
@ -32,3 +32,5 @@ yarn-error.log*
|
|||||||
|
|
||||||
# vercel
|
# vercel
|
||||||
.vercel
|
.vercel
|
||||||
|
|
||||||
|
.vscode/
|
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.next/
|
||||||
|
node_modules/
|
||||||
|
.vscode/
|
||||||
|
.github/
|
@ -1 +1,3 @@
|
|||||||
# ugra-hackathon_frontend
|
# 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"]
|
||||||
|
}
|
@ -1,7 +1,15 @@
|
|||||||
import "../styles/globals.css";
|
import React from 'react'
|
||||||
|
|
||||||
|
import "styles/globals.css";
|
||||||
|
import { CounterProvider } from "context/counterContext";
|
||||||
|
|
||||||
function MyApp({ Component, pageProps }) {
|
function MyApp({ Component, pageProps }) {
|
||||||
return <Component {...pageProps} />;
|
return (
|
||||||
|
// Здесь компонент Component оборачиваем провайдеры глобального контекста. Если контекст используется не во всём приложении, а в каком-то определённом компоненте и его дочерних элементах, стоит занести провайдер туда
|
||||||
|
<CounterProvider>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</CounterProvider>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MyApp;
|
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
|
@ -1,3 +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() {
|
export default function Home() {
|
||||||
return <></>;
|
return (
|
||||||
|
<>
|
||||||
|
<ExampleComponent />
|
||||||
|
<PowerfulComponent />
|
||||||
|
<Link href="/counter">
|
||||||
|
<a>Simplifyed counter</a>
|
||||||
|
</Link>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
}
|
@ -12,7 +12,8 @@
|
|||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve"
|
"jsx": "preserve",
|
||||||
|
"baseUrl": "."
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user