Хочешь уверенно проходить IT-интервью?

Мы понимаем, как сложно подготовиться: стресс, алгоритмы, вопросы, от которых голова идёт кругом. Но с AI тренажёром всё гораздо проще.
💡 Почему Т1 тренажёр — это мастхэв?
- Получишь настоящую обратную связь: где затык, что подтянуть и как стать лучше
- Научишься не только решать задачи, но и объяснять своё решение так, чтобы интервьюер сказал: "Вау!".
- Освоишь все этапы собеседования, от вопросов по алгоритмам до диалога о твоих целях.
Зачем листать миллион туториалов? Просто зайди в Т1 тренажёр, потренируйся и уверенно удиви интервьюеров. Мы не обещаем лёгкой прогулки, но обещаем, что будешь готов!
Реклама. ООО «Смарт Гико», ИНН 7743264341. Erid 2VtzqwP8vqy
Вам помогут переиспользуемые блоки кода! Переиспользуемые блоки кода – то, что нужно прогрессивному разработчику!
Современный фронтенд крепко стоит на компонентах, потому что это действительно разумный и приятный подход к разработке. Собирать программу из «кирпичиков Lego» существенно проще и надежнее, чем с нуля писать монолит.
Так бросим же все силы на то, чтобы научиться мыслить в компонентном стиле!
Учимся готовить компоненты
Казалось бы, каждый джун сегодня умеет писать компоненты, чему тут учиться? Но компонент компоненту рознь, для наших программ нужны только самые качественные и красивые из них. Поэтому сейчас мы возьмем неограненный React-компонент, который написал простой разработчик вроде вас, и рассмотрим его очень пристально со всех сторон. А затем много-много раз отрефакторим, пока не получится идеальный бриллиант.
Будьте готовы к многочисленным озарениям и головокружительному увеличению вашей производительности!
Исходный компонент
Рассмотрим неограненный алмаз, с которым мы будем работать. Этот простой компонент умеет не так уж и много:
- он получает с бэкенда список браузеров;
- отображает индикатор загрузки, пока запрос выполняется;
- выводит полученные данные в виде карточек;
- если пользователь нажимает на карточку, компонент показывает модальное окно с детальной информацией о браузере.
Этот код похож на ваш?
import React, { useEffect, useState } from 'react';
import { FlatList, Text, View, StyleSheet, Modal, TouchableOpacity } from 'react-native';
import AddModal from '../components/AddModal';
import LoadingIndicator from '../components/LoadingIndicator'
import BrowserItem from '../components/BrowserItem'
import colors from '../config/colors';
function Browsers() {
const URL = 'https://google.com/myData.json'
// Элемент массива
// {"Browsers":[
// {
// "fullname": "Chrome",
// "linkToBrowser": "https://google.com",
// "image": "https://linktoimage.com/chrome.png",
// "minMemory": "1 GB",
// "currentVersion": "29.0.1",
// "minimumRAM": "2 GB",
// "description": "How much RAM do you have? Ha-ha",
// "windows": true,
// "mac": true,
// "linux": true,
// "ubuntu": true,
// "fedora": false,
// "stars": 4,
// "id":"chrome"
// },
// ...
// ]
// }
const [loading, setLoading] = useState(true)
const [browsers, setBrowsers] = useState([])
const [modalVisible, setModalVisible] = useState(false)
const [description, setDescription] = useState("")
const changeDescription = (description) => {
setDescription(description)
setModalVisible(!modalVisible)
}
const changeOpacity = () => {
setModalVisible(!modalVisible)
console.log('changeOpacity')
}
useEffect(() => {
fetch(URL)
.then((response) => response.json())
.then((responseJson) => {
return responseJson.Browsers
})
.then(browsers => {
setBrowsers(browsers)
// console.log(browsers)
setLoading(false)
})
.catch(error => {
console.log(error)
})
.finally(() => setLoading(false));
}, [])
return (
<View style={styles.container}>
{loading ? (
<LoadingIndicator />
) : (
<View>
<AddModal
modalVisible={modalVisible}
changeOpacity = {() => changeOpacity()}
description={description}
/>
<FlatList
data={browsers}
keyExtractor={browser => browser.fullname}
renderItem={({ item }) =>
<BrowserItem
fullname={item.fullname}
image={item.image}
linkToBrowser={item.linkToBrowser}
minMemory={item.minMemory}
currentVersion={item.currentVersion}
minimumRAM={item.minimumRAM}
description={item.description}
windows={item.windows}
mac={item.mac}
linux={item.linux}
ubuntu={item.ubuntu}
fedora={item.fedora}
stars={item.stars}
changeDescription={() => changeDescription(item.description)}
/>
}
/>
</View>
)
}
</View >
);
};
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center'
},
})
export default Browsers;
Что с этим компонентом так?
Что с этим компонентом не так?
К чему мы стремимся?
Искусство быстрой разработки – это искусство создания переиспользуемых блоков кода.
Чем больше у вас разных кирпичиков, тем быстрее вы можете построить дом.
- Не нужно повторять одно и то же по десять раз – помним о принципе DRY!
- Не нужно вносить изменения в нескольких местах – и лихорадочно вспоминать, где еще есть этот функционал.
- Не нужно ловить баги по всему приложению – они смирно сидят в компоненте и ждут вас.
- Не нужно много читать, код сразу становится короче, чище и понятнее.
- Не нужно писать тесты для каждого места, в котором используется функциональность.
Приступаем к огранке
Начнем с самых простых приемов рефакторинга, а затем войдем во вкус и сдеаем что-то посложнее.
Шаг #1. Перенос констант в пропсы
function Browsers({url = 'https://google.com/myData.json'}) {
const URL = url
...
Одно элементарное действие – и наш компонент уже может работать с другим URL. Маленький шаг для разработчика, но огромный прыжок для переиспользуемого блока!
Шаг #2. Разделение бизнес-логики и отображения
Вероятно, это самая важная фундаментальная установка хорошего разработчика – разделение бизнес-логики от логики отображения. Жизнь становится проще, когда UI компоненты ничего не знают о серверах, логике и состоянии приложения.
В чем вообще разница?
Бизнес-логика: Код, который принимает решения и изменяет состояния. Все внутри <Browsers/>
до инструкции return
.
Логика отображения: код, который отображает состояние приложения на экране и взаимодействует с пользователем. Все внутри инструкции return
в нашем примере.
Давайте произведем радикальное рассечение компонента на две части и убедимся, что жизнь действительно стала проще:
- Пользовательский хук
useBrowsers()
с бизнес-логикой. - Компонент
<BrowsersList />
с логикой отображения.
import React, {useEffect, useState} from 'react'
import {FlatList, StyleSheet, View} from 'react-native'
import AddModal from '../components/AddModal'
import LoadingIndicator from '../components/LoadingIndicator'
import BrowserItem from '../components/BrowserItem'
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
},
})
function useBrowsers(url) {
const [loading, setLoading] = useState(true)
const [browsers, setBrowsers] = useState([])
const [modalVisible, setModalVisible] = useState(false)
const [description, setDescription] = useState('')
const changeDescription = (description) => {
setDescription(description)
setModalVisible(!modalVisible)
}
const changeOpacity = () => {
setModalVisible(!modalVisible)
console.log('changeOpacity')
}
useEffect(() => {
fetch(URL)
.then((response) => response.json())
.then((responseJson) => {
return responseJson.Browsers
})
.then((browsers) => {
setBrowsers(browsers)
// console.log(browsers)
setLoading(false)
})
.catch((error) => {
console.log(error)
})
.finally(() => setLoading(false))
}, [])
return {
loading,
browsers,
modalVisible,
description,
changeDescription,
changeOpacity,
}
}
function BrowsersList({
loading,
browsers,
modalVisible,
description,
changeDescription,
changeOpacity,
}) {
return (
<View style={styles.container}>
{loading ? (
<LoadingIndicator />
) : (
<View>
<AddModal
modalVisible={modalVisible}
changeOpacity={() => changeOpacity()}
description={description}
/>
<FlatList
data={browsers}
keyExtractor={(browser) => browser.fullname}
renderItem={({item}) => (
<BrowserItem
fullname={item.fullname}
image={item.image}
linkToBrowser={item.linkToBrowser}
minMemory={item.minMemory}
currentVersion={item.currentVersion}
minimumRAM={item.minimumRAM}
description={item.description}
windows={item.windows}
mac={item.mac}
linux={item.linux}
ubuntu={item.ubuntu}
fedora={item.fedora}
stars={item.stars}
changeDescription={() => changeDescription(item.description)}
/>
)}
/>
</View>
)}
</View>
)
}
function Browsers() {
return <BrowsersList {...useBrowsers('https://google.com/myData.json')} />
}
export default Browsers
Код все еще далек от идеала, но уже стал немного более удобным.
<BrowsersList />
теперь можно использовать с разными источниками данных (а не только с данными из HTTP-эндпоинтов).useBrowsers()
теперь может работать с разными представлениями или даже вообще без представления. Если вы измените дизайн приложения, этот хук продолжит работать.
Шаг #3. Разделение на файлы
Разделение монолита на две части открыло широкий простор для нового рефакторинга. Чтобы программа стала еще более читаемой и годной к переиспользованию, разделим код на отдельные изолированные модули. Как говорится, чем изолированнее, тем реюзабельнее.

Это файловая структура типичного React-проекта:
- index.js экспортирует
<Browsers/>
из Browsers.jsx; - строительные блоки для
<Browsers/>
лежат в папках components и hooks;
BrowsersList.jsx можно развить до самостоятельной папки с собственными хуками, компонентами и файлом index.js

Посмотрим на BrowsersList.jsx:
import React from 'react'
import {FlatList, StyleSheet, View} from 'react-native'
import AddModal from '../../../components/AddModal'
import LoadingIndicator from '../../../components/LoadingIndicator'
import BrowserItem from '../../../components/BrowserItem'
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
},
})
export function BrowsersList({
loading,
browsers,
modalVisible,
description,
changeDescription,
changeOpacity,
}) {
return (
<View style={styles.container}>
{loading ? (
<LoadingIndicator />
) : (
<View>
<AddModal
modalVisible={modalVisible}
changeOpacity={() => changeOpacity()}
description={description}
/>
<FlatList
data={browsers}
keyExtractor={(browser) => browser.fullname}
renderItem={({item}) => (
<BrowserItem
fullname={item.fullname}
image={item.image}
linkToBrowser={item.linkToBrowser}
minMemory={item.minMemory}
currentVersion={item.currentVersion}
minimumRAM={item.minimumRAM}
description={item.description}
windows={item.windows}
mac={item.mac}
linux={item.linux}
ubuntu={item.ubuntu}
fedora={item.fedora}
stars={item.stars}
changeDescription={() => changeDescription(item.description)}
/>
)}
/>
</View>
)}
</View>
)
}
Прежде чем волшебным образом превратить этого гадкого утенка в реюзабельного прекрасного лебедя, давайте поговорим о Большой Проблеме.
Большая проблема маленьких файлов
Взгляните на сигнатуру функции <BrowsersList />
. Что произойдет, если мы переименуем какой-нибудь пропс, например, changeDescription
на setSelectedBrowser
? Или удалим аргумент? Или добавим новый?
Все сломается!
Каждый раз когда вы меняете сигнатуру компонента, возникает проблема во всех местах, где он используется. А вы не раз будете менять эту несчастную сигнатуру, потому что с первого раза редко получается хорошо. Ваша IDE это не отследит, придется ручками искать все вызовы и вносить правки. Это медленно и совсем не круто. Даже более: искать теперь придется по разным файлам, связь между которыми не всегда очевидна.
Ну и где профит-то, спросите вы? Опять что-нибудь где-нибудь забудем исправить – и прощай продакшн.
Посмотрите внимательно, все ли тут в порядке?
Файл useBrowsers.js:
...
return {
loading,
browsers,
modalVisible,
descripton,
changeDescription,
changeOpacity,
}
...
Файл BrowsersList.jsx:
...
export function BrowsersList({
loading,
browsers,
modalVisible,
description,
changeDescription,
changeOpacity,
}) {
....
Бинго! Одна маленькая опечатка – и все идет кувырком.
Сколько прекрасных часов проводят молодые разработчики, сравнивая пропсы и пытаясь понять, что же сломалось – но мы-то с вами уже не такие! Давайте решать проблему радикально.
Хватит медленно кодить на JS, давайте кодить быстро на TS
В 2021 году у вас нет оправданий, если вы не используете TypeScript. Вам даже не требуется сразу же изучить все его возможности, ведь можно просто добавить TS в проект, не меняя ни строчки, и постепенно наращивать его применение.

С TypeScript ваша IDE обогатится несколькими крутыми фичами:
- Автодополнение для пропсов

- Возможность автоматического переименования пропсов
- Проверка на null/undefined

- Валидация значений пропсов

А вот, кстати, и наша опечатка:

Шаг #4. Определение типов
Так как это не полноценный гайд по TypeScript, разбираться в основах мы сейчас не будем. Все желающие могут заглянуть на typescriptlang.org (или прочитать статью в «Библиотеке программиста» – прим. ред.). Вернемся к <BrowsersList />
и преобразуем его пропсы в симпатичные типы (не забудьте сменить расширение с .jsx на .tsx).
// ...
export type Browser = {
fullname: string // ожидается, что поле "fullname" - это строка
image: string
linkToBrowser: string
minMemory: string
currentVersion: string
minimumRAM: string
description: string
windows: boolean
mac: boolean
linux: boolean
ubuntu: boolean
fedora: boolean
stars: number
}
export type BrowsersListProps = {
loading: boolean
browsers: Browser[] // ожидается, что поле "browsers" это массив элементов с типом Browser
modalVisible: boolean
description: string
// ожидается, что changeDescription - это функция
// которая принимает строку и ничего не возвращает
changeDescription: (description: string) => void
// ожидается, что changeOpacity - это функция
// которая ничего не принимает и ничего не возвращает
changeOpacity: () => void
}
export function BrowsersList({
loading,
browsers,
modalVisible,
description,
changeDescription,
changeOpacity,
}: BrowsersListProps) {
return (
// ...
Теперь обновим сигнатуру useBrowsers()
:
import {useEffect, useState} from 'react'
import {BrowsersListProps} from '../components/BrowsersList'
export function useBrowsers(url: string): BrowsersListProps {
const [loading, setLoading] = useState(true)
// ...
И теперь TypeScript будет строго следить, чтобы useBrowsers()
и BrowsersList
были совместимы.
Быстрая разработка архитектуры
BrowsersListProps
выглядит весьма нагруженно:
export type BrowsersListProps = {
loading: boolean
browsers: Browser[]
modalVisible: boolean
description: string
changeDescription: (description: string) => void
changeOpacity: () => void
}
- Одна строчка – для состояния загрузки.
- Одна строчка – для списка браузеров.
- Целых четыре строчки – для отображения детальной информации о браузере в модальном окне. Есть большая вероятность, что потребуется выводить больше данных, а значит сигнатура может измениться. А это весьма беспокойное дело, как мы помним.
Мы можем уменьшить сложность этого фрагмента и отрефакторить функциональность модального окна для использования типа Browser
:

Этот маленький рефакторинг должен продемонстрировать вам замечательную способность TypeScript: быстро проектировать системный дизайн. Писать типы очень просто. Они маленькие, но содержат много полезной информации о вашей системе. Фактически вы можете описать вашу программу без кода, одними типами.
Теперь поправим <BrowserList />
, чтобы он мог работать с новой сигнатурой BrowsersListProps
.
Отрефакторим <BrowserItem />
. Сейчас он принимает множество пропсов, и это явный сигнал для внесения правок. Теперь он будет принимать всего 2 аргумента:
import React from 'react'
import {FlatList, StyleSheet, View} from 'react-native'
import AddModal from '../../../components/AddModal'
import LoadingIndicator from '../../../components/LoadingIndicator'
import BrowserItem from '../../../components/BrowserItem'
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
},
})
export type Browser = {
fullname: string
image: string
linkToBrowser: string
minMemory: string
currentVersion: string
minimumRAM: string
description: string
windows: boolean
mac: boolean
linux: boolean
ubuntu: boolean
fedora: boolean
stars: number
}
export type BrowsersListProps = {
loading: boolean
browsers?: Browser[]
selectedBrowser?: Browser
setSelectedBrowser: (browser?: Browser) => void
}
export function BrowsersList(props: BrowsersListProps) {
const {loading, selectedBrowser, setSelectedBrowser, browsers} = props
return (
<View style={styles.container}>
{loading ? (
<LoadingIndicator />
) : (
<View>
<AddModal
modalVisible={Boolean(selectedBrowser)}
onClose={() => setSelectedBrowser(undefined)}
description={selectedBrowser?.description}
/>
<FlatList
data={browsers}
keyExtractor={(browser) => browser.fullname}
renderItem={({item}) => (
<BrowserItem
browser={item}
onPress={() => setSelectedBrowser(item)}
/>
)}
/>
</View>
)}
</View>
)
}
Компонент стал проще и надежнее.
Шаг #5. Извлечение <UIFriendlyList />
Если вы немного помедитируете на компонент, то на вас снизойдет просветление. Список с "состоянием загрузки" – это очень крутая и востребованная функциональность, которая наверняка будет использоваться везде, где только можно.
Сейчас эта функциональность интегрирорована в <BrowsersList />
. Значит надо ее извлечь. Создадим новый компонент <UIFriendlyList />
и будем использовать его вместо простого <FlatList/ >
.
Как всегда начнем с определения типов:
type UIFriendlyListProps<T> = FlatListProps<T> & {loading?: boolean}
T
– это аргумент типа, или дженерик. То же самое, чтоarg
в сигнатуреfoo(arg)
. Дженерики нужны, если вы хотите создать свой тип из другого типа. Вот здесь есть подробнейшее описание дженериков.&
– это символ пересечения множеств (интерсекция). ТипX = A & B
означает, чтоX
содержит в себе свойстваA
иB
.
Итак, что мы сделали:
- Определили тип для пропсов нового компонента.
- Использовали дженерик, чтобы указать, что список может содержать элементы разных типов.
UIFriendlyListProps
расширяет встроенные классFlatListProps
из библиотеки React Native и добавляет в него состояние загрузки.
Теперь вынесем новый компонент в отдельный файл UIFriendlyList.jsx:
import React from 'react'
import {FlatList, FlatListProps, Text} from 'react-native'
import LoadingIndicator from './LoadingIndicator'
export type UIFriendlyListProps<T> = FlatListProps<T> & {loading?: boolean}
export function UIFriendlyList<T>(props: UIFriendlyListProps<T>) {
if (props.loading) {
return <LoadingIndicator />
}
if (props?.data && props.data.length === 0) {
return <Text>This list is empty (</Text>
}
return <FlatList {...props} />
}
Обратите внимание, мы добавили еще пустое состояние, чтобы показать юзеру, что список действительно пуст и он может больше не ждать загрузки. Это прекрасное решение с точки зрения UX.
Компонент <UIFriendlyList />
– это крутой строительный блок, который очень легко переиспользовать в самых разных ситуациях. Добавьте его в свою коллекцию кирпичиков, чтобы стать еще быстрее.
Во что теперь превратился наш <BrowsersList />
:
import React from 'react'
import {StyleSheet, View} from 'react-native'
import AddModal from '../../../components/AddModal'
import BrowserItem from '../../../components/BrowserItem'
import {UIFriendlyList} from '../../../components/UIFriendlyList'
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
},
})
export type Browser = {
fullname: string
image: string
linkToBrowser: string
minMemory: string
currentVersion: string
minimumRAM: string
description: string
windows: boolean
mac: boolean
linux: boolean
ubuntu: boolean
fedora: boolean
stars: number
}
export type BrowsersListProps = {
loading: boolean
browsers?: Browser[]
selectedBrowser?: Browser
setSelectedBrowser: (browser?: Browser) => void
}
export function BrowsersList(props: BrowsersListProps) {
const {loading, selectedBrowser, setSelectedBrowser, browsers} = props
return (
<View style={styles.container}>
<AddModal
modalVisible={Boolean(selectedBrowser)}
onClose={() => setSelectedBrowser(undefined)}
description={selectedBrowser?.description}
/>
<UIFriendlyList
loading={loading}
data={browsers}
renderItem={({item}) => (
<BrowserItem
key={item.fullname}
browser={item}
onPress={() => setSelectedBrowser(item)}
/>
)}
/>
</View>
)
}
Сравните его с исходным вариантом. Он почти в два раза меньше и гораздо проще для понимания. К тому же в качестве бонуса вы получили отличный компонент <UIFriendlyList />
, который в будущем сэкономит вам кучу времени. Можно пойти еще дальше и выделить, например, в отдельный кирпичик логику Модальное Окно со Списком, но давайте пока остановимся.
Процесс извлечения переиспользуемых фрагментов прекрасен, но бесконечен. В погоне за сомнительным идеалом вы можете потратить очень много времени в ущерб реальной продуктивности, поэтому нужно уметь останавливать себя.
Мы закончили с логикой отображения, пора вернуться к бизнес-логике.
Шаг #6. Рефакторинг useBrowsers()
Хук useBrowswers()
должен возвращать валидный объект с типом BrowsersListProps:
import {useEffect, useState} from 'react'
import {Browser, BrowsersListProps} from '../components/BrowsersList'
export function useBrowsers(url: string): BrowsersListProps {
const [loading, setLoading] = useState(false)
const [browsers, setBrowsers] = useState<Browser[]>([])
const [selectedBrowser, setSelectedBrowser] = useState<Browser | undefined>(
undefined,
)
useEffect(() => {
setLoading(true)
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
return responseJson.Browsers
})
.then((browsers) => {
setBrowsers(browsers)
})
.catch((error) => {
console.log(error)
})
.finally(() => setLoading(false))
}, [url])
return {
loading,
browsers,
selectedBrowser,
setSelectedBrowser,
}
}
Приглядимся повнимательнее. Функциональность "обратиться по некоторому URL и сохранить результат запроса, пока отображается индикатор загрузки" кажется весьма полезной, давайте извлечем ее в новый хук useFetch
.
Как всегда, сначала типы. Нам нужно, чтобы useFetch сохранял данные из эндпоинта и отображал состояние загрузки. Формат данных будет задан отдельно, для этого используем дженерик:
export type FetchBrowsersResults = {
Browsers: Browser[]
}
export type UseFetch<T> = {
loading: boolean
// We use Generic. T - is a type argument that can be any type.
// We can useFetch() with any type
// ? means, that T can be undefined
data?: T
}
export function useFetch<T>(url: string): UseFetch<T> {}
Таким образом, useFetch
можно будет использовать с любыми типами данных.
Теперь сама функция:
import {useEffect, useState} from 'react'
import {Alert} from 'react-native'
export type UseFetch<T> = {
loading: boolean
data?: T
}
export function useFetch<T>(url: string): UseFetch<T> {
const [loading, setLoading] = useState<boolean>(false)
const [data, setData] = useState<T | undefined>(undefined)
useEffect(() => {
setLoading(true)
fetch(url)
.then((response) => response.json())
.then(setData)
.finally(() => setLoading(false))
.catch((error) => Alert.alert('Fetch error', error))
}, [url])
return {
loading,
data,
}
}
Для полноты картины добавили Alert
при ошибке запроса.
Теперь окончательно отрефакторим useBrowsers()
:
import {useState} from 'react'
import {Browser, BrowsersListProps} from '../components/BrowsersList'
import {useFetch} from '../../../hooks/useFetch'
export type FetchBrowsersResults = {
Browsers: Browser[]
}
export function useBrowsers(url: string): BrowsersListProps {
const {loading, data} = useFetch<FetchBrowsersResults>(url)
const [selectedBrowser, setSelectedBrowser] = useState<Browser | undefined>(
undefined,
)
return {
loading,
browsers: data?.Browsers,
selectedBrowser,
setSelectedBrowser,
}
}
Сравните с исходным вариантом.
Кажется, здесь больше нечего извлекать :)
4 простых совета для ускорения разработки
1. Никогда не форматируйте код вручную.
Используйте возможности IDE, ESLint и Prettier.

2. Никогда не импортируйте модули вручную
Использование автоматического импорта сэкономит много времени.

3. Научитесь ориентироваться среди множества файлов
Разделяя проект на маленькие переиспользуемые кирпичики вы неизбежно приходите к монструозной файловой структуре вроде этой:

Привыкните использовать возможности IDE: поисковую строку для поиска компонентов, горячие клавиши для перемещения по истории файлов и всплывающие определения, которые появляются при наведении курсора на название компонентов.
4. Используйте линтинг
Это поможет найти самые хитрые и вредные ошибки:

Искусство быстрой разработки
Чтобы быть быстрым, не потеряв при этом в качестве, вам нужно освоить несколько вещей:
- Отделять бизнес-логику от отображения.
- Разделять код на маленькие реюзабельные компоненты.
- Использовать TypeScript и начинать работу с определения типов.
- Практиковаться в рефакторинге.
- Использовать плюшки вашей IDE.
Насколько вы постигли дзен быстрой разработки? Признавайтесь, часто рефакторите?
Дополнительные материалы:
Комментарии