Detalizēta apmācība: kā lietot Shopify Storefront API ar React un Redux

E-komercija visiem! (… Tīmekļa vietnes, tas ir, )

Raksta Kriss 2018. gada augusts, atjaunināts 2018. gada novembrī

Pieklājīgi no negatīvās telpas vietnē pexels.com

Pamatinformācija un motivācija

Tātad motivācija šeit bija diezgan vienkārša. Es gribēju, lai manu vietņu apmeklētāji varētu pārlūkot, meklēt un atlasīt produktus tieši manā pielāgotajā domēnā, neizejot uz mūsu vietni Shopify.

Sekundārā motivācija ir tāda, ka man drīzāk būtu sava vietņu kodu bāze, nevis viena no Shopify rūpnīcas veidnēm. Nav apvainojumu Shopify komanda! Veidnes ir modernas un tīras, taču tās ir diezgan pamata. Es esmu pārliecināts, ka šīs veidnes ir ļoti pielāgojamas, taču tā šobrīd nav man zināma kaudze.

Tātad, tas ir labākais no abām pasaulēm - mana pielāgotā vietne React (jau izveidota un tiešsaistē ) ar pievienoto API un Shopify izrakstīšanās procesu!

Pēc šīs apmācības beigām jūs varēsit pievienot savus Shopify produktus jebkurā savas vietnes lapā. Vienīgā iepirkšanās procesa daļa, kas notiks Shopify, ir tad, kad lietotājs noklikšķina uz “Checkout”.

Arī šai apmācībai esmu izveidojis tukšu katlu krātuvi.

Motivācija tieši šeit rakstīšanai Medium bija tāda, ka es pats nevarēju atrast apmācību par šo procesu - tāpēc es nolēmu to izveidot!

Es esmu bijis profesionāls izstrādātājs jau 4 gadus un programmēšana septiņiem gadiem. Es esmu strādājis tehnikas komplektos no vecās skolas Fortran un Perl līdz React, Javascript, Python un Node.

Siren Apparel ir viens no maniem blakus projektiem / startup / maker uzņēmumiem, kuru vadu jau 5 gadus, un līdz šim esam ziedojuši 5 dažādām policijas un ugunsdzēsības nodaļām!

Sāksim beidzot sākt ar šo mācību.

Shopify Storefront API

Brīnišķīgie Shopify ļaudis ir izveidojuši Storefront API. Izmantojot Storefront API, jūs varat izveidot komponentus React, lai pievienotu produktu attēlus, produktu variantus, produktu izmērus, grozu un pogas “pievienot grozam” un “izrakstīšanās” savai vietnei, kas nav Shopify.

* Ņemiet vērā, ka šī apmācība NAV par Shopify Polaris, kas tiek izmantota, lai izveidotu komponentus React pašā Shopify veikala pārvaldībā.

Darba sākšana: react-js-buy Repository

Apskatiet šo React piemēru, ko izveidojusi Shopify komanda. Lielākā daļa šīs apmācības koda nāk no šīs krātuves.

… Vai jūs paskatījāties? Labi!

Tagad mēs ielēksimies kodā! Dodieties uz savas React vietnes saknes mapi un ar termināļa palīdzību instalējiet shopify-buy moduli:

cd my-awesome-react-project /
npm instalēt - saglabājiet veikalu, nopērciet

(vai dzijai pievienojiet shopify-buy, ja vēlaties dziju)

Pēc tam savā priekšnodokļa index.js (NOT App.js!) Jums būs jāimportē klients no JS Buy SDK:

importēt klientu no 'shopify-buy';

Pēc tam virs ReactDOM.render () zvana pievienojiet šādu konfigurācijas objektu:

const klients = Client.buildClient ({
    storefrontAccessToken: “jūsu piekļuves pilnvara”,
    domēns: “jūsu-shopify-url.myshopify.com”
});

Tas ir šobrīd index.js - mēs pie tā drīz atgriezīsimies.

Tagad mēs pievienosim visus komponentus, kas nepieciešami vienmērīgai iepirkšanās un izrakstīšanās pieredzei. Kopējiet visas sastāvdaļas no react-js-buy repozitorija:

Cart.js

LineItem.js

Produkts.js

Produkti.js

VariantSelector.js

Mēs ielīmēsim šos komponentus jūsu src / mapē esošajos komponentos / shopify / mapē. Jūs varētu ievietot šos komponentu failus jebkur citur src / mapē, ja vēlaties. Pārējā apmācības daļa paredz, ka esat tos ievietojis komponentos / shopify /.

App.js mainīšana

App.js būs jāveic plašas izmaiņas. Vispirms importējiet to iepirkumu komponentu, kuru tikko iekopējāt, savā projektā:

importa grozs no './components/shopify/Cart';

Ja jūsu App.js komponents nebija bezvalstnieks, tāpat kā mans, jums droši jākopē visa šī konstruktora () funkcija:

konstruktors () {
    super ();
    this.updateQuantityInCart = this.updateQuantityInCart.bind (this);
    this.removeLineItemInCart = this.removeLineItemInCart.bind (this);
    this.handleCartClose = this.handleCartClose.bind (this);
}

Ja jums jau ir štats, kopējiet tikai tās saistītās līnijas. Šīs trīs līnijas ir notikumu apstrādātāja funkcijas, kurām Shopify grozam ir jāfunkcionē pareizi.

"Bet kā ir ar groza stāvokli!?"

Jūs varat jautāt; vai:

"Kā būtu ar šo notikumu apstrādātāju noteikšanu grozam !?"

Patiešām, tas nāk, bet vēl ne!

Tad jūs varat pievienot komponentu renderēšanas () funkcijas apakšdaļai pirms div. Beigām.

Manuprāt, grozam ir jābūt pieejamai jebkur jūsu lietotnē. Manuprāt, ir jēga ievietot komponentu jūsu lietotnes saknes komponentā - citiem vārdiem sakot, App.js:

atgriezties (
...
);

Atkal es pagaidām neesmu iekļāvis kodu notikumu apstrādātājos. Turklāt es nerunāju par to, ka App.js grozā nebija valsts komponentu.

Tam ir labs iemesls.

Aptuveni šī projekta pusceļā es sapratu, ka mana produkta sastāvdaļa, protams, nav manā App.js failā.

Tā vietā tika aprakti apmēram trīs bērnu komponenti.

Tā vietā, lai produktus nodotu bērniem trīs līmeņos, un pēc tam funkciju apstrādātāji visu ceļu atpakaļ uz augšu ...

Es nolēmu izmantot…

Redux !!!

Ugh! Es zinu, es zinu, ka Redux, lai arī tas nav ļoti grūti, ir sāpes% * $! sākotnēji pieslēgt visu nepieciešamo apkures katlu. Bet, ja jūs esat izstrādātājs, kas strādā pie e-komercijas veikala vai e-komercijas veikala īpašnieks, domājiet par to šādi: Redux ļaus jums piekļūt groza stāvoklim no jebkura mūsu vietnes komponenta vai lapas vai tīmekļa vietnes.

Šī spēja būs būtiska, paplašinoties Siren Apparel un attīstot vairāk produktu. Tā kā mēs izveidojam vairāk produktu, es izveidošu atsevišķu veikala lapu ar visiem produktiem, mājas lapā atstājot tikai nedaudzus piedāvātos produktus.

Spēja piekļūt grozam ir būtiska, ja lietotājs mazliet iepērkas, nolasa dažus stāstus vai informāciju par Siren Apparel un pēc tam nolemj veikt norēķinus. Nav svarīgi, cik daudz viņi pārvietojas, nekas no viņu groza netiks zaudēts!

Tātad, īsi sakot, es nolēmu, ka, iespējams, ir labāk ieviest Redux tagad, kamēr mūsu vietnes kodu bāze nav pārāk liela.

Īstenojot Redux vietnei Shopify, iegādājieties SDK ar minimālu katlu plātni

Instalējiet NPM pakotnes redux un react-redux:

npm instalēt - saglabājiet redux react-redux

Indeksā.js importējiet pakalpojumu sniedzēju no react-redux un savu veikalu no ./store:

importēt {Provider} no 'react-redux';
importa veikals no './store';

Aptiniet komponentu ar nodoto veikalu ap jūsu indeksā.jsto, lai jūsu App pievienotu jūsu Redux veikalam:

ReactDOM.render (

    
      
    
 ,
document.getElementById ('sakne')
);

(Ņemiet vērā, ka man ir arī , taču tas ir citā rakstā par to, kā es piemēroju internacionalizāciju un lokalizāciju, lai dinamiski padarītu saturu Siren Apparel vietnē. Atšķirīgs stāsts citai dienai.)

Protams, mēs vēl neesam izveidojuši ./store.js failu. Izveidojiet savu veikalu veikalā store.js, izmantojot src / root, un ievietojiet to šeit:

importēt {izveidotStore} no 'redux';
importa samazinātājs no './reducers/cart';
eksportēt noklusējuma createStore (reduktoru);

Izveidojiet reduktoru failu src / reduktoros / cart.js un ielīmējiet šo kodu:

// sākotnējais stāvoklis
const initState = {
  isCartOpen: nepatiess,
  kase: {lineItems: []},
  produkti: [],
  veikals: {}
}
// darbības
const CLIENT_CREATED = 'CLIENT_CREATED'
const PRODUCTS_FOUND = 'PRODUCTS_FOUND'
const CHECKOUT_FOUND = 'CHECKOUT_FOUND'
const SHOP_FOUND = 'SHOP_FOUND'
const ADD_VARIANT_TO_CART = 'ADD_VARIANT_TO_CART'
const UPDATE_QUANTITY_IN_CART = 'UPDATE_QUANTITY_IN_CART'
const REMOVE_LINE_ITEM_IN_CART = 'REMOVE_LINE_ITEM_IN_CART'
const OPEN_CART = 'OPEN_CART'
const CLOSE_CART = 'CLOSE_CART'
// reduktori
eksporta noklusējums (stāvoklis = initState, darbība) => {
  slēdzis (action.type) {
    lieta CLIENT_CREATED:
      atgriezties {... štats, klients: action.payload}
    lieta PRODUCTS_FOUND:
      atgriezt {... stāvokli, produktus: action.payload}
    lieta CHECKOUT_FOUND:
      atgriezties {... štatā, kasē: action.payload}
    lieta SHOP_FOUND:
      atgriezties {... štatā, veikalā: action.payload}
    gadījums ADD_VARIANT_TO_CART:
      atgriezt {... state, isCartOpen: action.payload.isCartOpen, checkout: action.payload.checkout}
    gadījums UPDATE_QUANTITY_IN_CART:
      atgriezties {... štatā, kasē: action.payload.checkout}
    lieta REMOVE_LINE_ITEM_IN_CART:
      atgriezties {... štatā, kasē: action.payload.checkout}
    gadījums OPEN_CART:
      atgriezties {... stāvoklī, isCartOpen: true}
    lieta CLOSE_CART:
      atgriezt {... state, isCartOpen: false}
    noklusējums:
      atgriešanās stāvoklis
  }
}

Neuztraucieties, es negaidīšu tikai šo lielo reduktoru un neapspriedīšu notiekošo; mēs nokļūsim katrā pasākumā! Šeit jāņem vērā dažas lietas.

Sākotnējo stāvokli ņem no stāvokļa rakstīšanas, kā tas ir Shopify GitHub piemērā, un ievieto to mūsu initState, proti, šādās četrās stāvokļa daļās:

isCartOpen: nepatiess,
kase: {lineItems: []},
produkti: [],
veikals: {}

Tomēr, īstenojot, es arī izveidoju klienta daļu no valsts. Es vienreiz izsaucu funkciju createClient () un pēc tam to nekavējoties ievietoju Redux stāvoklī index.js. Tāpēc iesim indeksā.js:

Atpakaļ uz index.js

const klients = Client.buildClient ({
  storefrontAccessToken: “jūsu veikals-marķieris”,
  domēns: “jūsu-shopify-url.myshopify.com”
});
store.dispatch ({tips: 'CLIENT_CREATED', derīgā krava: klients});

Shopify pirkt SDK piemērā ir daži asinhronu izsaukumi, lai iegūtu informāciju par produktiem un saglabātu informāciju React funkcijā componentsWillMount (). Šis koda piemērs izskatās šādi:

componentsWillMount () {
    this.props.client.checkout.create (). tad ((res) => {
      this.setState ({
        izrakstīšanās: res,
      });
    });
this.props.client.product.fetchAll (). tad ((res) => {
      this.setState ({
        produkti: res,
      });
    });
this.props.client.shop.fetchInfo (). tad ((res) => {
      this.setState ({
        veikals: res,
      });
    });
  }

Es izvēlējos to darīt, cik vien iespējams augšpus vietnes ielādes, tieši index.js. Pēc tam, kad tika saņemta katra atbildes daļa, es izsludināju atbilstošu notikumu:

// buildClient () ir sinhrona, tāpēc mēs visus šos varam izsaukt pēc tam!
client.product.fetchAll ()., tad ((res) => {
  store.dispatch ({tips: 'PRODUCTS_FOUND', derīgā krava: res});
});
client.checkout.create ()., tad ((res) => {
  store.dispatch ({tips: 'CHECKOUT_FOUND', derīgā krava: res});
});
client.shop.fetchInfo ()., tad ((res) => {
  store.dispatch ({tips: 'SHOP_FOUND', derīgā krava: res});
});

Tagad reduktors ir izveidots, un Shopify API klienta inicializācija ir pabeigta visiem, kas paredzēti indeksam.js.

Atpakaļ uz App.js

Tagad App.js pieslēdziet Redux veikalu App stāvoklim:

importēt {savienot} no 'react-redux';

un neaizmirstiet importēt arī veikalu:

importa veikals no './store';

Apakšā, kur vajadzētu būt eksporta noklusējuma lietotnei, mainiet to uz šo:

eksportēt noklusējuma savienojumu ((stāvoklis) => stāvoklis) (lietotne);

Tas savieno Redux stāvokli ar komponentu App.

Tagad render () funkcijā mēs varam piekļūt Redux stāvoklim, izmantojot Redux's getState () (kā paredzēts vaniļas reaģēšanas funkcijai this.state):

render () {
    ...
    const state = store.getState ();
}

Visbeidzot: notikumu apstrādātāji (mēs joprojām atrodamies App.js)

No augšas jūs zināt, ka App.js ir nepieciešami tikai trīs notikumu apstrādātāji, jo grozā tiek izmantoti tikai trīs: updateQuantityInCart, removeLineItemInCart un handleCartClose. Oriģinālie groza notikumu apstrādātāji no GitHub krātuves krājuma, piemēram, vietējā komponenta stāvokļa, izskatījās šādi:

updateQuantityInCart (lineItemId, daudzums) {
  const checkoutId = this.state.checkout.id
  const lineItemsToUpdate = [{id: lineItemId, daudzums: parseInt (daudzums, 10)}]
atgriezt šo.props.client.checkout.updateLineItems (checkoutId, lineItemsToUpdate) .tad (res => {
    this.setState ({
      izrakstīšanās: res,
    });
  });
}
removeLineItemInCart (lineItemId) {
  const checkoutId = this.state.checkout.id
atgrieziet šo.props.client.checkout.removeLineItems (checkoutId, [lineItemId]). pēc tam (res => {
    this.setState ({
      izrakstīšanās: res,
    });
  });
}
handleCartClose () {
  this.setState ({
    isCartOpen: nepatiess,
  });
}

Mēs varam viņus reaģēt, lai nosūtītu notikumus uz Redux veikalu šādi:

updateQuantityInCart (lineItemId, daudzums) {
    const state = store.getState (); // štats no redux veikala
    const checkoutId = state.checkout.id
    const lineItemsToUpdate = [{id: lineItemId, daudzums: parseInt (daudzums, 10)}]
    state.client.checkout.updateLineItems (checkoutId, lineItemsToUpdate). tad (res => {
      store.dispatch ({tips: 'UPDATE_QUANTITY_IN_CART', derīgā krava: {izrakstīšanās: res}});
    });
}
removeLineItemInCart (lineItemId) {
    const state = store.getState (); // štats no redux veikala
    const checkoutId = state.checkout.id
    state.client.checkout.removeLineItems (checkoutId, [lineItemId]). pēc tam (res => {
      store.dispatch ({tips: 'REMOVE_LINE_ITEM_IN_CART', derīgā krava: {izrakstīšanās: res}});
    });
}
handleCartClose () {
    store.dispatch ({tips: 'CLOSE_CART'});
}
handleCartOpen () {
    store.dispatch ({tips: 'OPEN_CART'});
}

Ja jūs sekojāt līdzi, es jau pieminēju, ka es pievienoju savu handleCartOpen funkciju, jo es šo funkciju nododu kā atbalstu manam