О чем вам не расскажут на курсах по Реакту. Вредные советы, как стать незаменимым разработчиком

от автора

Если ваша задача — не просто научиться писать код, а понять, как стать тем, без кого поддержка и развитие проекта просто немыслимы, то этот текст для вас. Заодно поговорим о том, как помочь коллегам постичь дзен и досконально изучить структуру разрабатываемого приложения.

Всем привет, меня зовут Макс Кравец, я CEO IT-компании Holyweb, и сегодня хочу поделиться вредными советами о том, как стать незаменимым React-разработчиком. Поехали!

Волшебный спред-оператор 

Вам поставили задачу написать компонент, приветствующий пользователя. Нет ничего легче — обращаемся к объекту, который хранит имя и фамилию, и добавляем их к приветствию:

export function Welcome({name, surname}) {   return (     <div>       Привет, {name} {surname}     </div>   ) }

Но на странице приветствие выводится в составе другого компонента, предположим, это хедер. А значит — нужно пробросить параметры. Как поступит новичок? Сядет и методично распишет все в коде родителя:

export function Header({ user }) {   return (     <div>       <Welcome          name={user.name}         surname={user.surname}       />       <div>         Some other code...       </div>     </div>   ); }

В целом — это работает. Но такой код разберет любой другой новичок, ведь движение пропсов по древу компонентов прозрачно! Кроме того, параметров может быть не два, а два десятка. Представляете, сколько времени придется потратить, сколько строк кода написать?

Ловите лайфхак:

export function Header({ user }) {   return (     <div>       <Welcome {...user}/>       <div>         Some other code...       </div>     </div>   ); }

Магия спред-оператора — код стал проще, короче, не нужно расписывать каждый параметр. А главное — никто, кроме вас, теперь не может при беглом взгляде на хедер понять, какие именно поля из объекта user на самом деле нужны в компоненте приветствия. 

Вот таким нехитрым способом можно и время сэкономить, и +100 в скилл «незаменимость» себе добавить — пусть только попробуют от вас избавиться, себе дороже выйдет! 

Техника Props Drilling 

Если писать код, беспокоясь только о реализации бизнес-логики, можно даже не заметить, как попадешь в ловушку. 

Простейшая задача: пишем составной компонент, который выводит в банковском приложении информацию о счете клиента. Тип счета задается на верхнем уровне, а отрисовывает его компонент в глубине иерархии. Создаем контекст, определяем провайдер, присваиваем значение…

export const AccountType = createContext()  export function TopComponent() {   return (     <AccountType.Provider value="credit">       <MiddleComponent />     </AccountType.Provider>    ); }  export function MiddleComponent() {   return (     <LowComponent />   ); }  export function LowComponent() {   return (     <DeepComponent />   ); }  export function DeepComponent() {   const accountType = useContext(AccountType);    return (     <span> {accountType} account</span>   ); }

Код выше — воплощение цифрового эгоизма. Судите сами — вашему коллеге достаточно разобраться, где контекст провайдится, и где выводится. А вся остальная иерархия остается без внимания. Хорошо, когда все нужные компоненты выстроены в одном файле друг за дружкой, но где вы такое в реальном проекте видели? 

На помощь приходит техника Props Drilling — просто объявите нужное свойство на самом верху древа компонентов и методично прокиньте до места использования.

export function TopComponent() {   const account = {     accountType: "credit"   }    return (       <MiddleComponent account={account} />   ); }  export function MiddleComponent({account}) {   return (     <LowComponent account={account} />   ); }  export function LowComponent({account}) {   return (     <DeepComponent account={account}/>   ); }  export function DeepComponent({account}) {    return (     <span> {account.accountType} account</span>   ); }

Бинго! Даже если компоненты разнесены по разным папкам проекта, ни один не останется без внимания ваших коллег в процессе поиска возможной ошибки. А чтобы не бросать и этот процесс на самотек и гарантированно заработать искреннюю благодарность соратников по работе, можно где-то в середине цепочки изменить или даже обнулить свойство:

… export function MiddleComponent({account}) {    account.accountType = null    return (     <LowComponent account={account} />   ); } …

Простыми компонентами никого не удивишь

Ну вот и пришло время для серьезной задачи: готовим компонент, который выводит данные карты пользователя приложения. При этом номер карты и CVV по умолчанию должны быть скрыты и отображаться при клике/тапе по соответствующему полю, ФИО — отображаться в виде «имя сокращено до одной буквы, фамилия полностью, все заглавными буквами». Кроме того, нужно предусмотреть возможность копирования номера карты и CVV в буфер обмена.

Сначала пройдем по простому пути, а потом разберем, в чем была ошибка. Напишем функцию, которая будет отправлять нужные данные в буфер обмена

const copyToClipBoard = data => {   const textField = document.createElement('textarea')   textField.innerText = data   document.body.appendChild(textField)   textField.select()   document.execCommand('copy')   textField.remove()   alert('Скопировано в буфер обмена') }

добавим разбиение номера карты на группы

const formatNumber = cardNumber => {   let cNumToStr = ''     let it = 0      String(cardNumber).split('').forEach((s) => {     if (it % 4 === 0) {       cNumToStr = cNumToStr + ' '     }     cNumToStr = cNumToStr + s     it++   })   return cNumToStr }

напишем компонент, который выводит номер карты, предусмотрев вариант скрытия первых трех групп чисел и возможность копирования данных

export function CardNumberComponent({cardNumber}) {   const [isShow, setIsShow] = useState(false)      const toggle = () => {setIsShow(!isShow)}       const showNumber = isShow      ? formatNumber(cardNumber)     : "•••• " + formatNumber(cardNumber).substring(formatNumber(cardNumber).length - 4)    return (     <div>       <p>Номер карты</p>       <div onClick={toggle}> {showNumber} </div>       <button onClick={() => copyToClipBoard(cardNumber)}>копировать</button>     </div>   ) }

аналогичным образом разберемся с CVV

export function CardCVVComponent({cvv}) {   const [isShow, setIsShow] = useState(false)      const toggle = () => {setIsShow(!isShow)}     const showCVV = isShow     ? cvv     : "•••"        return (     <div>       <p>CVV</p>       <div onClick={toggle}> {showCVV} </div>       <button onClick={() => copyToClipBoard(cvv)}>копировать</button>     </div>   ) }

Напишем компонент, который выводит срок действия карты

export function CardExpireComponent({expire}) {   return (     <div>       <p>Срок действия</p>       {expire.year}/{expire.month}     </div>   ) }

и данные владельца

export function CardUserNameComponent({user}) {   const userInfo = (user.name[0] + '. ' + user.surname).toUpperCase()    return (     <div>       <p>Владелец</p>       <div>{userInfo}</div>       <button onClick={() => copyToClipBoard(userInfo)}>копировать</button>     </div>   ) }

Ну и последним действием соберем все вместе

export function CardComponent() {    return (     <>       <CardNumberComponent cardNumber={cardInfo.cardNumber}></CardNumberComponent>       <CardExpireComponent expire={cardInfo.expire}></CardExpireComponent>       <CardCVVComponent cvv={cardInfo.cvv}></CardCVVComponent>       <CardUserNameComponent user={user}></CardUserNameComponent>     </>   ) }

Источниками данных будут служить объект информации о пользователе и объект информации о карте

const user = {   name: 'Ivan',   surname: 'Ivanov', }  const cardInfo = {   cardNumber: "1234567812345678",   expire: {     year: 24,     month: 11   },   cvv: 123 }

Как говорится — получите, распишитесь. Но присмотритесь внимательно, что мы накодили в результате? Пара простых функций, несколько небольших компонентов. Срамота, да и только! Этим не похвастаешься перед коллегами, да и начальству не объяснишь, что задача была трудна и неплохо бы подумать о премии. 

Выход — вспомнить о том, что нас просили сделать компонент, который выводит данные о карте. Один. Давайте исправим наш код.

export function CardComponent() {    const copyToClipBoard = data => {     const textField = document.createElement('textarea')     textField.innerText = data     document.body.appendChild(textField)     textField.select()     document.execCommand('copy')     textField.remove()     alert('Скопировано в буфер обмена')   }       const [isShowNumber, setIsShowNumber] = useState(false)   const [isShow, setIsShow] = useState(false)   const toggleNumber = () => {setIsShowNumber(!isShowNumber)}    const toggleCVV = () => {setIsShow(!isShow)}    const userInfo = (user.name[0] + '. ' + user.surname).toUpperCase()   let cNumToStr = ''   let it = 0      String(cardInfo.cardNumber).split('').forEach((s) => {     if (it % 4 === 0) {       cNumToStr = cNumToStr + ' '     }     cNumToStr = cNumToStr + s     it++     return cNumToStr   })      const showNumber = isShowNumber      ? cNumToStr     : "•••• " + cNumToStr.substring(cNumToStr.length - 4)    const showCVV = isShow     ? cardInfo.cvv     : "•••"       return (     <>       <div>         <p>Номер карты</p>         <div onClick={toggleNumber}> {showNumber} </div>         <button onClick={() => copyToClipBoard(cardInfo.cardNumber)}>копировать</button>       </div>       <div>         <p>Срок действия</p>         {cardInfo.expire.year}/{cardInfo.expire.month}      </div>      <div>        <p>CVV</p>        <div onClick={toggleCVV}> {showCVV} </div>        <button onClick={() => copyToClipBoard(cardInfo.cvv)}>копировать</button>      </div>      <div>         <p>Владелец</p>         <div>{userInfo}</div>         <button onClick={() => copyToClipBoard(userInfo)}>копировать</button>     </div>      </>   ) }

Согласитесь, выглядит гораздо солиднее? Мало того, что весь функционал в одном месте, так еще и можно быть уверенным — проще будет позвать вас, как автора, чем разобраться, что в этом компоненте к чему относится. А значит — смело можно добавлять +500 в скилл «незаменимость».

Что в итоге?

Разумеется, секретов у настоящего мастера много, и выше приведены далеко не все. Ищите сами, добавляйте свои варианты в комментарии. Но помните, что при этом главное — не перегнуть палку. А то можно стать настолько незаменимым, что никто и на работу взять не рискнет.

Если хотите продолжения, пишите в комментарии или мне в Телеграм, и мы выпустим продолжение подборки незаменимых советов для реакт-мастеров 🙂 

Другие наши статьи: 


ссылка на оригинал статьи https://habr.com/ru/post/650131/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *