Added some code styling tips and examples

This commit is contained in:
Dmitriy Shishkov 2020-11-26 23:21:08 +05:00
parent c0cb43a4c5
commit 1b3fc394c1
No known key found for this signature in database
GPG Key ID: D76D70029F55183E
14 changed files with 153 additions and 4 deletions

2
.gitignore vendored
View File

@ -32,3 +32,5 @@ yarn-error.log*
# vercel
.vercel
.vscode/

4
.prettierignore Normal file
View File

@ -0,0 +1,4 @@
.next/
node_modules/
.vscode/
.github/

View File

@ -1 +1,3 @@
# ugra-hackathon_frontend
Training project to get another members of team used to code style

View 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;

View File

@ -0,0 +1,11 @@
// Лучше писать документацию на функции, за это будет респект от менторов
/**
* Increase counter
* @param {SetStateAction} setCounter
*/
const handleCounterClick = (setCounter) => {
return () => setCounter((prev) => prev + 1); // Если используем контекст, тогда замыкаем всё, что нужно внутри обработчика
};
// Экспорт лучше делать отдельно, чтобы всегда знать, что мы экспортируем из файла, а что используем внутри (как с public/private методами)
export { handleCounterClick };

View 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
View 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
View 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
View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"module": "esnext",
"target": "es5",
"baseUrl": "."
},
"exclude": ["node_modules", ".next"]
}

View File

@ -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 }) {
return <Component {...pageProps} />;
return (
// Здесь компонент Component оборачиваем провайдеры глобального контекста. Если контекст используется не во всём приложении, а в каком-то определённом компоненте и его дочерних элементах, стоит занести провайдер туда
<CounterProvider>
<Component {...pageProps} />
</CounterProvider>
);
}
export default MyApp;

15
pages/counter.tsx Normal file
View 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

View File

@ -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() {
return <></>;
return (
<>
<ExampleComponent />
<PowerfulComponent />
<Link href="/counter">
<a>Simplifyed counter</a>
</Link>
</>
);
}

View File

@ -0,0 +1,6 @@
/* Благодаря использованию css-modules можно использовать одни и те же названия классов
в разных компонентах и ничего нам за это не будет, ибо при сборке к ним добавятся хеши */
.button {
background-color: red;
color: white;
}

View File

@ -12,7 +12,8 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
"jsx": "preserve",
"baseUrl": "."
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]