Üksikasjalik õpetus: kuidas kasutada Shopify Storefront API-d koos React ja Reduxiga

E-kaubandus kõigile! (… Veebisaidid, see tähendab )

Kirjutanud Chris August 2018, värskendatud november 2018

Pexels.com saidi negatiivse ruumi viisakalt

Taust ja motivatsioon

Seega oli siinne motivatsioon üsna lihtne. Tahtsin, et minu saidi külastajad saaksid sirvida, otsida ja tooteid otse oma kohandatud domeenis sirvida, neid otsida, ilma et peaksime minema meie Shopify saidile.

Teisene motivatsioon on see, et mul oleks pigem veebisaidi jaoks oma koodipõhi, kui kasutada ühte Shopify tehase malle. Pole rikkumist Shopify meeskond! Mallid on kaasaegsed ja puhtad, kuid need on üsna põhilised. Olen kindel, et neid malle on raske kohandada, kuid see ei ole praegu minu teada virn.

Nii et see on mõlemast maailmast parim - minu kohandatud Reacti sait (juba üles ehitatud ja veebis ), millele on lisatud API ja Shopify väljaostuprotsess!

Selle õpetuse lõpuks saate oma Shopify tooteid lisada oma saidi mis tahes lehele. Ainuke Shopify ostuprotsessi osa on see, kui kasutaja klõpsab nupul „Checkout”.

Olen selle õpetuse jaoks loonud ka tühja katlamajahoidla.

Spetsiaalselt meediumil kirjutamiseks oli motivatsiooniks lihtsalt see, et ma ei leidnud ise selle protsessi õpetust - seega otsustasin selle teha!

Olen olnud professionaalne arendaja juba neli aastat ja programmeerimine seitse. Olen töötanud tehnikakodades alates vana kooli Fortranist ja Perlist kuni Reaktini, Javascripti, Pythoni ja Node-ni.

Siren Apparel on üks minu kõrvalprojektide / idufirmade / tegijate ettevõtteid, mida ma juhin juba 5 aastat ja mida oleme seni annetanud 5 erinevale politsei- ja tuletõrjeosakonnale!

Alustame lõpuks selle õpetusega.

Shopify Storefront API

Shopify imelised inimesed on kokku pannud Storefront API. Poe Storefront API abil saate luua komponente React, et lisada toodete pilte, tootevariante, toote suurusi, ostukorvi ning nuppe „Lisa ostukorvi” ja „Checkout” omaenda saidile, mis pole Shopify.

* Pange tähele, et see õpetus EI OLE Shopify Polarise kohta, mida kasutatakse komponentide loomiseks rakenduses React Shopify poehalduse enda jaoks.

Alustamine: react-js-buy hoidla

Heitke pilk sellele Shopteki meeskonna ehitatud React näitele. Enamik selle juhendaja koodi pärineb sellest hoidlast.

… Kas vaatasite? Tore!

Nüüd hakkame otse koodi sisestama! Minge oma Reacti saidi juurkausta ja installige terminali kaudu shopify-buy moodul:

cd minu-vinge-reageeri-projekt /
npm install - salvestage kauplus-ostke

(või lõnga lisage shopify-osta, kui eelistate lõnga)

Seejärel peate oma esiplaanil index.js (MITTE App.js!) Importima kliendi JS Buy SDK-st:

importige klient kauplusest-ostke;

Seejärel lisage ReactDOM.render () kõne kohale järgmine konfiguratsiooniobjekt:

const klient = Client.buildClient ({
    storefrontAccessToken: „teie juurdepääsuluba”,
    domeen: 'teie-poodista-url.myshopify.com'
});

See on praegu index.js jaoks - tuleme selle juurde varsti tagasi.

Nüüd lisame kõik komponendid, mis on vajalikud sujuvaks ostlemiseks ja kassas kasutamiseks. Kopeerige kõik komponendid react-js-buy hoidlast:

Cart.js

LineItem.js

Toote.js

Tooted.js

VariantSelector.js

Kleepime need komponendid teie src / kausta acomponents / shopify / kausta. Saate need komponentfailid kuhu iganes mujale kausta src / kausta panna, kui soovite. Ülejäänud õpetuses eeldatakse, et olete need komponentidesse / shopify / pannud.

Rakenduse App.js muutmine

App.js vajab põhjalikke muudatusi. Esiteks importige see komponent, mille te just kopeerisite, oma projekti:

impordi ostukorvi './components/shopify/Cart';

Kui teie App.js komponent oli kodakondsuseta, nagu minu oma, peaksite kogu selle konstruktori () funktsiooni ohutult kopeerima:

ehitaja () {
    Super();
    this.updateQuantityInCart = this.updateQuantityInCart.bind (see);
    this.removeLineItemInCart = this.removeLineItemInCart.bind (see);
    this.handleCartClose = this.handleCartClose.bind (this);
}

Kui teil juba on olek, kopeerige ainult need köidetud read. Need kolm rida on sündmuste käitleja funktsioonid, mida Shopify ostukorv peab korralikult töötama.

"Aga kuidas on vankriga olekus !?"

Võite küsida; või:

"Aga kuidas määratleda need sündmuste käitlejad ostukorvi !?"

Tõepoolest, see on tulekul, kuid mitte veel!

Seejärel saate komponendi lisada oma renderduse () funktsiooni lõppu enne lõppu div.

Minu arvates peaks ostukorv olema juurdepääsetav kõikjal teie rakenduses. Arvan, et siis on mõistlik lisada komponent oma rakenduse juurkomponenti - teisisõnu, App.js:

tagasi (
...
);

Jällegi pole ma veel ostukorvi lisanud sündmuste käitlejate koodi. Lisaks ei käsitlenud ma rakenduse App.js ostukorvis olekukomponentide puudumist.

Selleks on mõjuv põhjus.

Umbes poolel teel sellele projektile sain aru, et minu toodete komponent polnud muidugi minu App.js failis.

Selle asemel maeti sinna umbes kolm komponenti.

Nii et selle asemel, et tooteid kolm taset lastele alla lasta ja selle asemel funktsioonide käitlejad kogu varundada ...

Otsustasin kasutada…

Redux !!!

Kuule! Ma tean, ma tean, et Reduxil pole kuigi raskusi, kuid see on% * $ valu! juhtima esialgu kogu vajaliku katlaplaadiga. Kui olete aga e-poe kaupluse arendaja või e-poe poe omanik, mõelge sellele nii: Redux võimaldab teil päästa ostukorvi olekut meie veebisaidi või webapi mis tahes komponendi või lehe kaudu.

See võime on oluline, kui Siren Apparel laieneb ja me arendame rohkem tooteid. Kui loome rohkem tooteid, teen kõigi toodete jaoks eraldi spetsiaalse poe lehe, jättes kodulehele vaid käputäis esiletoodud tooteid.

Ostukorvi sisenemise võimalus on hädavajalik, kui kasutaja natuke ringi poeb, loeb Siren Apparel kohta lugusid või teavet ja otsustab siis kassata. Pole tähtis, kui palju nad ringi liikuvad, nende ostukorvist ei kao midagi!

Nii et lühidalt otsustasin, et ilmselt on parem Redux nüüd kasutusele võtta, kuigi meie saidi koodbaas pole liiga suur.

Shopify Reduxi installimine Osta SDK minimaalse katlaplaadiga

Installige NPM-i paketid redux ja react-redux:

npm install - salvestage redux reagect-redux

Importige kataloogis index.js pakkuja react-redux ja teie pood ./store:

importige {pakkuja} rakendusest 'react-redux';
impordi pood './store';

Mähkige komponent möödunud poodiga oma kataloogi ümber index.jsto, et ühendada oma rakendus oma Reduxi poodi:

ReactDOM.render (

    
      
    
 ,
document.getElementById ('juur')
);

(Pange tähele, et mul on ka , kuid see on teises postituses selle kohta, kuidas ma rakendasin rahvusvahelistumist ja lokaliseerimist, et muuta dünaamiliseks sisu Siren Apparel saidil. Erinevaks päevaks erinev lugu.)

Muidugi pole me veel ./store.js faili veel teinud. Looge oma pood saidil store.js src / root ja pange see sinna:

import {looStore} kaustast 'redux';
impordi reduktor './reducers/cart' -st;
eksport vaikimisi createStore (reduktor);

Looge reduktorite fail kataloogis src / reduktorid / cart.js ja kleepige see kood:

// algseisund
const initState = {
  isCartOpen: vale,
  kassasse: {lineItems: []},
  tooted: [],
  pood: {}
}
// toimingud
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'
// reduktorid
eksport vaikimisi (olek = initState, toiming) => {
  lüliti (action.type) {
    juhtum CLIENT_CREATED:
      tagastama {... riik, klient: action.payload}
    juhtum PRODUCTS_FOUND:
      tagasta {... riik, tooted: action.payload}
    juhtum CHECKOUT_FOUND:
      tagastama {... olek, kassasse jõudmine: action.payload}
    juhtum SHOP_FOUND:
      tagastama {... riik, pood: action.payload}
    juhtum ADD_VARIANT_TO_CART:
      tagastama {... olek, isCartOpen: action.payload.isCartOpen, kassasse: action.payload.checkout}
    juhtum UPDATE_QUANTITY_IN_CART:
      tagastama {... olek, kassasse jõudmine: action.payload.checkout}
    juhtum REMOVE_LINE_ITEM_IN_CART:
      tagastama {... olek, kassasse jõudmine: action.payload.checkout}
    juhtum OPEN_CART:
      return {... olek, isCartOpen: true}
    juhtum CLOSE_CART:
      return {... olek, isCartOpen: vale}
    vaikimisi:
      naasmisolek
  }
}

Ärge muretsege, ma ei hakka lihtsalt seda suurt reduktorit postitama ega arutama, mis toimub; me jõuame igale üritusele! Siin tuleb tähele panna mõnda asja.

Võtame algse oleku sellest, mida olek on kirjutatud, nagu näiteks Shopify GitHubi näites, ja paneme selle meie initState'i, nimelt järgmisesse osariiki:

isCartOpen: vale,
kassasse: {lineItems: []},
tooted: [],
pood: {}

Kuid oma teostuses loon ka riigi kliendiosa. Kutsun üks kord funktsiooni createClient () ja sean selle siis kohe reduxi olekusse index.js. Vaatame siis index.js-i:

Tagasi lehele index.js

const klient = Client.buildClient ({
  storefrontAccessToken: 'teie-pood-märk',
  domeen: 'teie-poodista-url.myshopify.com'
});
store.dispatch ({tüüp: 'CLIENT_CREATED', kasulik koormus: klient});

Shopify osta SDK-näites on mõned asünkroonikõned toodete kohta teabe saamiseks ja teabe salvestamiseks Reacti funktsioonis komponentWillMount (). See näidiskood näeb välja järgmine:

komponentWillMount () {
    this.props.client.checkout.create (). siis ((res) => {
      this.setState ({
        kassasse: res,
      });
    });
this.props.client.product.fetchAll (). siis ((res) => {
      this.setState ({
        tooted: res,
      });
    });
this.props.client.shop.fetchInfo (). siis ((res) => {
      this.setState ({
        kauplus: res,
      });
    });
  }

Valisin selle asemel saidi laadimisest võimalikult ülesvoolu otse index.js-s. Seejärel kuulutasin vastuse iga osa laekumise järel välja vastava sündmuse:

// buildClient () on sünkroonne, nii et võime neile kõigile helistada pärast!
klient.product.fetchAll (). siis ((res) => {
  store.dispatch ({tüüp: 'PRODUCTS_FOUND', kasulik koormus: res});
});
klient.checkout.create (). siis ((res) => {
  store.dispatch ({tüüp: 'CHECKOUT_FOUND', kasulik koormus: res});
});
klient.shop.fetchInfo (). siis ((res) => {
  store.dispatch ({tüüp: 'SHOP_FOUND', kasulik koormus: res});
});

Nüüdseks on reduktor loodud ja Shopify API kliendi initsialiseerimine on index.js jaoks valmis.

Tagasi rakendusse.js

Nüüd ühendage App.js Reduxi pood Appi olekusse:

impordi {connect} rakendusest 'react-redux';

ja ärge unustage ka poodi importida:

impordi pood './store';

Muutke selle allosas, kus peaks olema vaikerakenduse eksportimine, seda järgmiselt:

eksport vaikimisi ühenda ((olek) => olek) (rakendus);

See ühendab Reduxi oleku rakenduse komponendiga.

Nüüd renderdamise () funktsioonis pääseb Reduxi olekule juurde Reduxi getState () abil (nagu vaniljereakti kasutamisel on see.state):

renderdama () {
    ...
    const olek = store.getState ();
}

Lõpuks: sündmuste käitlejad (oleme endiselt App.js-is)

Ülaltpoolt teate, et rakenduses App.js on ainult kolm sündmusekäitlejat, mida vajame, kuna ostukorv kasutab ainult kolme: updateQuantityInCart, removeLineItemInCart ja handleCartClose. GitHubi näitehoidla näited, mis kasutasid kohaliku komponendi olekut, nägid välja nii:

updateQuantityInCart (lineItemId, kogus) {
  const checkoutId = this.state.checkout.id
  const lineItemsToUpdate = [{id: lineItemId, kogus: parseInt (kogus, 10)}]
tagastage see.props.client.checkout.updateLineItems (checkoutId, lineItemsToUpdate). siis (res => {
    this.setState ({
      kassasse: res,
    });
  });
}
removeLineItemInCart (lineItemId) {
  const checkoutId = this.state.checkout.id
tagastage see.props.client.checkout.removeLineItems (checkoutId, [lineItemId]). siis (res => {
    this.setState ({
      kassasse: res,
    });
  });
}
handleCartClose () {
  this.setState ({
    isCartOpen: vale,
  });
}

Saame neile reageerida, et saata sündmused Reduxi poodi järgmiselt:

updateQuantityInCart (lineItemId, kogus) {
    const olek = store.getState (); // osariik reduxi poest
    const checkoutId = state.checkout.id
    const lineItemsToUpdate = [{id: lineItemId, kogus: parseInt (kogus, 10)}]
    state.client.checkout.updateLineItems (checkoutId, lineItemsToUpdate). seejärel (res => {
      store.dispatch ({tüüp: 'UPDATE_QUANTITY_IN_CART', kasulik koormus: {checkout: res}});
    });
}
removeLineItemInCart (lineItemId) {
    const olek = store.getState (); // osariik reduxi poest
    const checkoutId = state.checkout.id
    state.client.checkout.removeLineItems (checkoutId, [lineItemId]). siis (res => {
      store.dispatch ({tüüp: 'REMOVE_LINE_ITEM_IN_CART', kasulik koormus: {checkout: res}});
    });
}
handleCartClose () {
    store.dispatch ({tüüp: 'CLOSE_CART'});
}
handleCartOpen () {
    store.dispatch ({tüüp: 'OPEN_CART'});
}

Kui te jälgisite, siis juba mainisin, et lisasin oma käepidemeCartOpen, kuna kannan selle funktsiooni tugiteenusena alla oma