JSX: как разделять логику и отрисовку в разметке, сгенерированной методом map

от автора

Давайте представим себе частый кейс — вы с бека получаете какой-то массив данных, из которых вы будете делать разметку, что будет содержимым вашей страницы.

Для примера возьмем список пользователей, и вам надо отрендерить этот список. Вам пришел массив и вы, не теряя времени, прогоняете его через map, создавая, таким образом свою разметку — вот так:

return (   <ul className="list">     {users.map(user => (       <Fragment key={user.name.name}>         <li>{user.name.name} {user.name.patronomic} {user.name.surname}</li>         <li>{user.regestrationDate}</li>         <li>{user.status.description}</li>       </Fragment>     ))}   </ul> );

Окей, тут все просто. Но давайте представим, что с бека (как это часто бывает) данные вам приходят не чистыми, но их еще надо обрабатывать. Например, отчества может не быть, то есть нужно сделать проверку, а имена и фамилии нужно привести к ловеркейсу.

Также при наличии даты регистрации, привести ее к нужному виду, а если нет, то сгенерить дату и отправить ее на бек.

Ну и напоследок, если статус нужно залить соответствующим стилем из заготовленного словаря, который завязан на отдельном свойстве value; если стиля в словаре нет — сделать какой-нибудь дефолтный.

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

Давайте представим как это могло бы выглядеть:

return (   <ul className="list">     {users.map(user => {       const fullName = `         {user.name.name}          {user.name.patronomic ? user.name.patronomic : ''}          {user.name.surname}       `.toLowerCase();       const date = user.regestrationDate          ? moment(user.regestrationDate)         : null;       const statusColor = ['В сети', 'Не в сети'].includes(         user.status.description,       )       ? STATUS_COLORS[user.status.value]       : 'neutral';        retrun (         <Fragment key={user.name.name}>           <li>{fullName}</li>           <li>{date}</li>           <li className={statusColor}>{user.status.description}</li>         </Fragment>       );     })}   </ul> );

Супер — всего 27 строк кода. А теперь представьте что у вас на проекте все это происходит в компоненте, где разметка занимает несколько сот строк кода (хотя бы). И такие простые утилитарные обработки отвлекают внимание и мешают увидеть общую картину разметки, а это в больших сложных проектах критично.

Что тут можно сделать? Я предлагаю выносить все утилитарные вычисления в отдельную функцию с префиксом «with» или «proxy», которая будет как некая «прослойка» содержать код расчета переменных и передавать их обратно в колбек, который занимается разметкой.

Продемонстрируем. Создадим функцию «withProxyUser», в которую обернем колбек разметки, перенесем в нее все переменные и передадим их обратно в колбек разметки с оригинальным обьектом user. Вот так:

const withProxyUser = callback => user => {   const fullName = `     {user.name.name}      {user.name.patronomic ? user.name.patronomic : ''}      {user.name.surname}   `.toLowerCase();      const date = user.regestrationDate      ? moment(user.regestrationDate)     : null;      const statusColor = ['В сети', 'Не в сети'].includes(     user.status.description,   )   ? STATUS_COLORS[user.status.value]   : 'neutral';    return callback({user, fullName, date, statusColor}); }  return (   <ul className="list">     {users.map(       withProxyUser(({user, fullName, date, statusColor}) => (         <Fragment key={user.name.name}>           <li>{fullName}</li>           <li>{date}</li>           <li className={statusColor}>{user.status.description}</li>         </Fragment>       ))     )}   </ul> );

Обратите внимание как объявляется функция withProxyUser — это множественный колбек. Чтобы не запутаться — первая переменная — это то что мы передаем в withProxyUser — то есть сам колбек; вторая переменная — то что мы получаем вне withProxyUser — то есть переменные из map.

И того наша разметка заметно «похудела», а про withProxyUser можно забыть — даже можно вынести ее в файл с утилитами, что еще больше разгрузит наш компонент.

Вот и все. Держите свою разметку в форме — пожалейте глаза и время коллег.

Спасибо.


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


Комментарии

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

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