Машинописните HOC с Apollo са доста трудни. Не знам може би съм само аз, но това...

Това е смущаващо, но несъмнено е необходимо. Как иначе искате компилаторът да проверява вашите реквизити в и извън обвития компонент? Ето как VSCode помощникът описва функцията graphql от react-apollo. Typescript не иска зло и ви защитава от самите вас.

Ще разработя и разширя примерите от apollo-graphql docs, тъй като им липсват някои случаи на употреба катоверига HOC или създаване на HOC на заявка с config.name , config.props.

Нека първо се потопим в graphql, създателя на HOC

  1. TProps — Интерфейс/Тип описва така наречените InputProps,забележете, че се разширява от TGraphQLVariables.
  2. TData — Тип за отговора от заявката.
  3. TGraphQLVariables — Тип за променливи, необходими за заявка/мутация.
  4. TChildProps — Този се генерира за вас въз основа на TData и TGraphQLVariables, освен ако не искате да бъде персонализиран.

DataPropsса реквизити, които ще бъдат генерирани за вас от TData и TGraphQLVariables, освен ако не предоставите персонализиран тип. Това се използва за типа на действие заявка. Той пакетира всички полезни свойства за контрол на заявките в обект data.

DataValueе тази, която предизвика у мен въпроси, главно защото обвива TDataсPartial. Този дизайн ще ви накара да проверите тези данни не е недефиниран във всеки потребител на HOC. За да го избегнете, можете да предоставите свой собствен TChildProps.

QueryControls са реквизити, които обикновено се опаковат в данни, сред тях има (след като заявката бъде разрешена) реквизитите, които въведохме като тип отговор, това се прави чрез пресичане на Partial‹TData› и QueryControls‹TData, TGraphQLVariables›

Няма да навлизам в повече подробности, разчленявайки QueryControls, защото смятам, че тази информация е достатъчна, за да се справя с целите на тази статия, в случай че сте склонни към повече проучване, не се колебайте да клонирате react- apollo и копайте по-дълбоко.

Нека да разгледаме най-простия пример за заявка с TS.

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

Заявка HOC без променливи

Нека първо разгледаме най-краткия възможен вариант.

withBurgersNoChildProps получава

  • TProps — {}
  • TDataОтговор
  • TGraphQLVariables —{} по подразбиране

TChildProps — ако е пропуснат, ще бъде генериран за вас като Частичен от предишните три типа. Това означава, че данни е незадължителна стойност и трябва да използвате ненулев оператор за твърдение — „!“ навсякъде. Има начин да избегнете тези проверки.

withBurgersWithChildProps получава

  • TProps — {}
  • TDataОтговор
  • TGraphQLVariables — {} по подразбиране
  • TChildProps получава ChildProps, вижте как използва ChildDataProps от react-apollo.

Нека да видим какво има под капака на типа ChildDataProps.

ChildDataPropsправи пресечна точка между TPropsиDataPropsс помощта на TDataиTGraphQLVvariables. Забележете, че този път няма Partial около DataProps, както беше в примера за дефиниция на graphql в стойността по подразбиране за TChildProps . Това означава, че данните определено ще присъстват в обвития компонент, което е удобно.

Заявка HOC с променливи

Ето примера за това как да подадете реквизити към вашия опакован компонент и да можете да ги валидирате.

За да получите правилния бургер,api се нуждае от име, в противен случай заявката ще се провали без него. Описах InputPropsкато интерфейс и го разширих от Variables, за да избегна дублиране на код, задължително е Variablesсъединени с InputProps, в противен случай TS компилаторът няма да знае какви подпориПроменливи са ви необходими за вашата заявка в graphql hoc.

Заявете HOC с config.options

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

Сега няма нужда да се разширява InputProps от Променливи, защото заявката за заявка ще бъде удовлетворена със заместване. TS също проверява типовете в декларацията на options object, така че няма да ви позволи да използвате свойство от различен тип от дадена Variable.

Заявете HOC с Options.name

Целта на това е, когато имате множество HOC на заявка, обвити около един единствен компонент, data prop, върнат от всички тях, в крайна сметка ще влезе в конфликт, така че давате на всяка заявка конкретно име.

За този пример всички знания отгоре трябва да бъдат подложени на тест. Защото сега ще напишем резултата от заявката в персонализирано име на свойство. Функцията graphqlняма да въведе тази вместо нас, така че трябва сами да напишем резултата от заявката за заявка.

withBurgerWithName— получава името на burgerRequest. burgerRequest вече ще съхранява всичко, което преди това е било съхранено в data, за да можем да го въведем, трябва да запомним как apollo въвежда data опора за нас. Трябва да имитираме типа ChildDataProps, ето негова съкратена версия.

type ChildDataProps = TProps & { data: DataValue<TData, TGraphQLVariables> }

Забележете как ръчно създадените ChildPropsотразяват структурата на ChildDataPropsс даннипреименувани на burgerRequest.

Верижни HOC заявки

Сега идва забавната част — въвеждане на веригата от HOC. Много от вас може би знаят за функцията съставяне от apollo. В пишещ текст той изхвърля всичките ви въведени текстове през прозореца. Ето дефиницията на функцията съставяне.

function compose(...funcs: Function[]): (...args: any[]) => any;

Съгласно това, съставяне е функция с къри. Първото му извикване приема функции, второто извикване приема всичко във всякакви количества, върнатата стойност е всяка.

Последиците

  1. Реквизитите, предадени отвън, не се валидират (вижте BurgerFactory)
  2. Реквизитите, предадени от HOC към обвит компонент, не са въведени (има всеки тип)

Нека първо коригираме втората точка.

Всичко, което трябва да направим, е изрично да напишем props в обвит компонент, което естествено бихте направили, ако използвате самостоятелен компонент вместо функция със стрелка.

За да коригираме първата точка, просто трябва да се откажем от използването на съставянесTypescript. Отказването от композиране води до най-простия вариант. Нека прегледаме примера, в който сме подготвили два HOC. Единият е донасяне на напитката, носи тривиалното име withBeverage, а другият е нашият добър стар приятел withBurger. Ще ви покажа как да ги задръстите заедно.

withBurger — този път без салата, нещата станаха наистина сериозни.

withBeverageе познат накратко, но отговаря на примера.

Комбинацията без композиране ще изглежда донякъде така

withBeverage(withBurger(MealComponent))

С конфигурацията на гореописаните HOC, компилаторът ще ни даде тази грешка

Интересуваме се от първия параграф.

'ComponentClass<BurgerInputProps, any>' is not assignable to parameter of type 'ComponentType<BeverageInputProps & BeverageVariables & { beverageRequest: DataValue<BeverageResponse, BeverageVariables>; }>'

Редът, започващ от ComponentType‹BeverageInputProps & …, описва компонента и неговитеPropTypes, върнати след извикване на withBeverage. Той е в конфликт с PropTypesна компонента, върнат от извикването на withBurger. За да коригираме тази грешка на компилатора, трябва да направим пресичания на върнатиятипотwithBeverageс входящите подпори типот с Бургер.

Първо на ред 2 създадох пресечна точка на BeverageInputProps и BurgerInputProps, това е необходимо за валидиране на входящите пропове, за да могат и двете заявки да се изпълняват правилно.

На ред 9 създадох пресечна точка на BurgerInputProps & BeverageChildProps, досега трябва да разберете, че тази е поставена в контейнер на TProps. Спомнете си по-рано, конфликтът на върнати пропси от withBeverage и получени пропси от withBurger,по този начинwithBurgerще разбере, че очаква не само специфични за променлива за заявка за бургер, но също и някои данни отwithBeverage.

Е, това е всичко, хора. Мисля да направя същата разяснителна статия за HOCs за Mutation, но не съм сигурен дали ще успея преди react-apollo да пусне своята версия с hooks за всичко и всички, включително мен, напълно ще забравят за HOCs.

Моля, не се колебайте да задавате въпроси, да давате съвети, да предлагате по-добри подходи в коментарите.