Мисли в React

Нашето мнение е, че React е най - добрия начин да изградите големи и бързи уеб приложения с Javascript. Получи се много добре за нас във Facebook и Instagram.

Едно от страхотните неща в React е как те кара да мислиш за приложението докато го разработваш. В този документ, ние ще преминем през целия процес на изграждане на таблица от продукти с React и ще добавим възможност за търсене.

Започнете С Примерни Данни

Представете си че вече имаме JSON API и дизайн. Като примерните данни изглеждат така:

Примерни данни

JSON API-то ни връща данни, които изглеждат така:

[
  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];

Стъпка 1: Разделете Визуалната Част В Йерархия От Компоненти

Първото нещо което бихте искали да направите е да нарисувате кутийки около всеки компонент (и подкомпонент) върху дизайна и да ги наименувате. Ако работите с дизайнери, те може вече да са направили това, така че отидете и говорете с тях. Накрая имената на Photoshop слоевете им може да се окажат имена на вашите React компоненти!

Но как да решите, кое трябва да е компонент? Просто използвайте същата техника, както когато трябва да създадете нова функция или обект. Такава техника е single responsibility principle, или накратко, в най - добрия случай компонента трябва да прави само едно, единствено нещо. Ако с времето продължава да се усложнява логиката, компонента трябва да се разбие на по-малки подкомпоненти.

Тъй като, често показваме JSON модел от данни на потребителя, ще откриете че ако вашия модел е направен правилно, вашия потребителски интерфейс (и следователно вашата структура от компоненти) ще напасне лесно. Това е така, защото потребителския интерфейс и модела от данни са склонни да се придържат, към една информационна архитектура, което означава, че често разделянето на интерфейса в компоненти е тривиално. Просто разбийте дизайна на компоненти, които представляват точно една частица от вашия модел от данни.

Диаграма на компонента

Ще видите, че имаме пет компонента в нашето малко приложение. Отбелязахме с курсив данните, които всеки компонент репрезентира.

  1. FilterableProductTable (оранжево): съдържа целия пример
  2. SearchBar (синьо): получава всички потребителски входни данни
  3. ProductTable (зелено): показва и филтрира колекция от данни базирана на потребителските входни данни
  4. ProductCategoryRow (тюркоаз): показва наименованието на всяка категория
  5. ProductRow (червено): показва ред за всеки продукт

Ако погледнете в ProductTable, ще забележите, че главната клетка на таблицата (съдържащи “Name” и “Price” надписи) не е собствен компонент. Това е въпрос на предпочитане и винаги може да има аргумент да се направи по друг начин. За този пример, ние го оставихме като част от ProductTable компонента, защото то е част от зареждането на колекцията от данни, което е задължение на ProductTable. Въпреки това, ако този компонент се усложни (т.е. ако добавим възможност за сортиране), то разбира се има смисъл да го направим отделен компонент ProductTableHeader.

Сега като избрахме компонентите от нашия дизайн, нека ги подредим в йерархия. Това е лесно. Компонентите, които се появяват в друг компонент в дизайна, трябва да се появяват като деца в йерархията:

  • FilterableProductTable

    • SearchBar
    • ProductTable

      • ProductCategoryRow
      • ProductRow

Стъпка 2: Изграждане На Статична Версия С React

Вижте примера Мисли в React: Стъпка 2 в CodePen.

Сега, когато имате йерархията на компонентите ви, е време да изградите вашето приложение. Най-лесният начин е да направите версия, която взима вашите данни и ги визуализира, без никаква интеракция. Най-добре ще е да не свързвате тези процеси, защото когато правите статична версия, това изисква много писане и малко мислене, докато добавянето на интеракция изисква много мислене и не толкова писане. Ще видим защо.

За да изградите статична версия, която визуализира вашите данни, ще искате първо да изградите компонентите, които преизползват други компоненти и подадете данните използвайки props. props е начина да подадете данни от родител към дете компонент. Ако сте запознати с концепцията на state, не използвайте state като цяло да изградите статична версия. State е запазена само за интеракции, това е, когато данните се сменят през някакво време. Нямате нужда от това, понеже това е статичната версия на приложението.

Може да изградите приложението отгоре-надолу или отдолу-нагоре. Това означава, че може да започнете с изграждането на компонентите които са най-високо в йерархията (т.е. да започнете с FilterableProductTable) или с някой от най-вътрешните компоненти (ProductRow). В по-прости примери, обикновенно е по-лесно да започнеш отгоре-надолу, но в големи проекти е по-лесно да започнете отдолу-нагоре и да пишете тестове докато изграждате компонентите.

Накрая на тази стъпка, ще имате библиотека от преизползваеми компоненти, които ще рендерират вашите данни. Компонентът ще има само render() метод, тъй като това е статична версия на вашето приложение. Компонентът на най-високо ниво в йерархията (FilterableProductTable) ще вземе данните ви като prop. Ако направите промени по основните ви данни и извикате ReactDOM.render() отново, интерфейса ще се промени. Лесно е да видите това и още къде да направите промените, понеже няма нищо сложно. React използва one-way data flow (също наречен one-way binding) подход, който държи всичко разделено на модули и работи бързо.

Просто отворете документацията на React ако се нуждаете от помощ за изпълнението на тази стъпка.

Кратка Пауза: Props vs State

Има два типа данни в React: props и state. Важно е да разберете разликата между двете; Погледнете официалната документация на React ако не сте сигурни, каква е разликата. Погледнете още FAQ: Каква е разликата между state и props?

Стъпка 3: Идентифицирай Минималното (но пълно) Представяне На UI State

За да направите своя UI интерактивен, трябва да сте способни да правите промени по основния модел от данни. React прави това лесно със state.

За да изградите правилно своето приложение, първо трябва да помислите за минималното количество променлив state, който приложението изисква. Тук ключа е DRY: Don’t Repeat Yourself. Разберете абсолютното минималното представяне на state-a, от който се нуждае вашето приложение и изчислете всичко останало от което се нуждаете при поискване. Например, ако правите приложение в което има списък със задачи, просто може да подържате масив от задачи. Не използвайте отделен state променлива за броя задачи. Също така, когато искате да визуализирате броя задачи, просто вземете дължината на масива със задачи.

Помислете за всички парчета от данни в нашето примерно приложение. Имаме:

  • Оригиналният списък от продукти
  • Търсеният текст, който потребителя е въвел
  • Стойноста на отметка
  • Филтрирания списък от продукти

Нека преминем през всеки един и преценим кой е state. Просто задай три въпроса за всяко едно парче от данни:

  1. Подаден ли е от родител чрез props? Ако да, то вероятно не е state.
  2. Остава ли непроменен през цялото време? Ако да, то вероятно не е state.
  3. Можете ли да го изчислите на база на всеки друг state или props в вашия компонент? Ако е така, то не е state.

Оригиналния списък от продукти се подава чрез props, така че не е state. Търсения текст и чекбокса изглеждат, че са state, понеже те се променят през времето и не могат да бъдат изчислени от нищо. И накрая, филтрираният списък от продукти не е state, защото може да бъде изчислен от комбинация на оригиналния списък от продукти с търсения текст и стойноста на чекбокса.

Накрая нашия state e:

  • Търсения текст, който потребителя е въвел
  • Стойноста на чекбокса

Стъпка 4: Разберете, Къде Трябва Да Живее Вашия State

Вижте примера Мисли в React: Стъпка 4 в CodePen.

Добре, ние открихме какво ще е минималното количество state в приложението. Следва да намерим кой компонент го променя, или притежава самия state.

Запомнете: React e само еднопосочен в пренасянето на данни надолу по йерархията от компоненти. Може би не е точно и ясно кой компонент трябва да притежава state. Често това е най-предизвикателната част за новите да разберат, следвайте тези стъпки, за да го разберете:

За всяко парче от state-та в твоето приложение:

  • Намерете всеки компонент, който рендерира нещо базирано на state.
  • Намерете общ главен компонент (компонент който е над всички компоненти в йерархията, които се нуждаят от state)
  • Единия от общия главен или друг компонент по-нагоре в йерархията, трябва да държат state.
  • Ако не можете да намерите компонент, където да има смисъл да се сложи собствен state, то просто създайте нов компонент, който има state и го добавете някъде в йерархията над общия главен компонент.

Нека преминем през тази стратегия за нашето приложение:

  • ProductTable трябва да филтрира списъка с продукти базиран на state-a и SearchBar трябва да визуализира търсения текст и проверения state.
  • Общият компонент, който ги обединява е FilterableProductTable.
  • Концептуално има логика филтрирания текст и проверените стойности да живеят в FilterableProductTable

Супер, решихме, че state-a ще живее в FilterableProductTable. Първо, добавете пропърти на инстанцията this.state = {filterText: '', inStockOnly: false} в constructor-а на FilterableProductTable за да рефлектира върху началния state на вашето приложение. Тогава, подайте filterText и inStockOnly на ProductTable и SearchBar като prop. И за финал, използвайте тези props, за да филтрирате редовете в ProductTable и ъпдейтнете стойностите на полетата на формата в SearchBar.

Може да започнете да гледате как се държи вашето приложение: ъпдейтнете filterText на "ball" и презаредете приложението. Ще видите, че таблицата с данни е ъпдейтната правилно.

Стъпка 5: Добавете Обратно Пренасяне На Данни

Вижте примера Мисли в React: Стъпка 5 в CodePen.

Досега, направихме приложение, което се зарежда правилно като функция от props и state, спускащи се надолу по йерархията. Сега е време да подържаме спускането на данни и в другата посока: компонента с формата е много навътре в йерархията, а трябва да обнови state-а в FilterableProductTable.

React прави това движение на данни експлицитно и прави вашата програма лесна за разбиране, как точно работи, но то не изисква повече писане от традиционното двупосочно свързване.

Ако се опитате да пишете или селектирате чекбокса в сегашната версия на примера, ще видите, че React игнорира въведения ви текст. Това е умишлено, понеже ние сложихме value prop на input да бъде винаги равен на state подаден от FilterableProductTable.

Нека помислим, какво точно искаме да се случи. Искаме да сме сигурни, че когато потребителя промени формата, обновяваме state-a с новите данни, въведени от потребителя. Тъй като компонентите трябва само да променят техния собствен state, FilterableProductTable ще подаде callbacks на SearchBar, който ще се стартира, когато state-а трябва да бъде ъпдейтнат. Може да използваме onChange event-a на инпутите, за да уведомим за него. Callbacks подадени от FilterableProductTable ще извикат setState(), и приложението ще се ъпдейтне.

Мислите че това звучи сложно, то е просто няколко реда код. Наистина е важно как данните ви се предават през цялото приложение.

И това е

Надяваме се, че това ще ви даде идея как да мислите за изграждането на компонентите и приложенията с React. Макар че може да има малко повече писане, отколкото сте свикнали, запомнете, че кода се чете много повече отколкото се пише, и е изключително по-лесно да се чете този добре написан и разделен на модули код. Като започнете да изграждате големи библиотеки от компоненти, ще оцените подробноста и модуларноста, и с преизползването на код, вашите редове код ще започнат да намаляват значително. :)