Részletes útmutatás: hogyan lehet használni a Shopify Storefront API-ját a React és a Redux használatával

E-kereskedelem mindenkinek! (… Webhelyek, azaz )

Írta: Chris, 2018. augusztus, frissítve: 2018. november

A negatív tér jóvoltából a pexels.com webhelyen

Háttér és motiváció

Tehát a motiváció itt nagyon egyszerű volt. Azt akartam, hogy a webhelyem látogatói képesek legyenek arra, hogy közvetlenül az egyéni domainben böngészjenek, kereshessenek és válasszanak termékeket anélkül, hogy el kellene menniük a Shopify webhelyünkre.

A másodlagos motiváció az, hogy inkább inkább saját weboldalammal rendelkezem, mint a Shopify gyári sablonjaival. Nincs sértés a Shopify csapatának! A sablonok modern és tiszta, de meglehetősen alapvetőek. Biztos vagyok benne, hogy ezek a sablonok nagymértékben testreszabhatók, de ez nem egy verem, amelyet jelenleg ismerek.

Tehát ez mindkét világ legjobbja - az egyéni React webhelyem (már beépített és online ), a hozzáadott API-val és a Shopify fizetési folyamatával!

Az oktatóanyag végére a Shopify termékeit a webhely bármely oldalára felveheti. A vásárlási folyamat egyetlen része, amely a Shopify-n fordul elő, az, amikor a felhasználó a „Pénztár” gombra kattint.

Ehhez az oktatóanyaghoz egy üres kazánlemezt is létrehoztam.

A kifejezetten a Mediumon való írás iránti motiváció egyszerűen az volt, hogy nem tudtam magamnak találni egy ismertetőt erről a folyamatról - ezért úgy döntöttem, hogy készítek egyet!

Már 4 éve profi fejlesztő vagyok, 7-nél programozom. Technológiában dolgoztam a régi iskola Fortran és Perl, a React, a Javascript, a Python és a Node technológiáig.

A Siren Apparel az egyik oldalsó projekt / induló / gyártó cég, amelyet 5 éve működtetök, és eddig öt különböző rendőrségi és tűzoltóságnak adományoztunk!

Most kezdjük el ezzel az oktatóanyaggal.

A Shopify Storefront API-ja

A Shopify csodálatos emberei összeállították a Storefront API-t. A Storefront API segítségével létrehozhat React összetevőket, hogy termékképeket, termékváltozatokat, termékméreteket, kosarat hozzáadhasson, és a „Kosárba adás” és a „Pénztár” gombokat adjon hozzá saját, nem Shopify webhelyéhez.

* Vegye figyelembe, hogy ez az oktatóprogram NEM vonatkozik a Shopify Polaris-ra, amelyet összetevők létrehozására használnak maga a Shopify üzletmenedzsment React számára.

Az első lépések: react-js-buy Repository

Vessen egy pillantást erre a React példára, amelyet a Shopify csapat készített. Az oktatóanyag legtöbb kódja az adott lerakatból származik.

… Megnézte? Jó!

Most rögtön a kódba ugorunk! Menjen a React webhely gyökérmappájába, és telepítse a shopify-buy modult a terminálon keresztül:

cd én-félelmetes-reagál-projekt /
npm telepítés - mentse el a boltok vásárlását

(vagy fonalat adjon hozzá shopify-buy-hez, ha kedveli a fonalat)

Ezután az index.js előlapjában (NEM App.js!) Importálnia kell az ügyfelet a JS Buy SDK-ból:

importálja az ügyfelet a „shopify-buy” -ból

Ezután adja hozzá a következő konfigurációs objektumot a ReactDOM.render () hívás fölé:

const kliens = Client.buildClient ({
    storefrontAccessToken: 'saját hozzáférési token',
    domain: 'your-shopify-url.myshopify.com'
});

Most ez az index.js esetében - hamarosan visszatérünk erre.

Most hozzáadunk minden olyan komponenst, amely szükséges a zökkenőmentes vásárláshoz és a pénztárhoz. Másolja az összes összetevőt a react-js-buy tárból:

Cart.js

LineItem.js

Product.js

Products.js

VariantSelector.js

Ezeket az összetevőket beillesztjük az src / mappában lévő összetevőkbe / shopify / mappába. Ezeket a komponens fájlokat bárhol máshol elhelyezheti az src / mappában, ha szeretné. Az oktatóprogram többi része feltételezi, hogy az összetevőkbe tették őket / shopify /.

Az App.js módosítása

Az App.js-hez alapos változtatásokra lesz szükség. Először importálja azt a kosar összetevőt, amelyet éppen lemásolt a saját projektébe:

import kosár a './components/shopify/Cart' -ból;

Ha az App.js komponens állapot nélküli volt, mint az enyém, akkor biztonságosan lemásolhatja az egész konstruktor () függvényt:

kivitelező () {
    szuper();
    this.updateQuantityInCart = this.updateQuantityInCart.bind (ez);
    this.removeLineItemInCart = this.removeLineItemInCart.bind (this);
    this.handleCartClose = this.handleCartClose.bind (this);
}

Ha már van állapota, akkor csak azokat a kötés sorokat másolja át. Ez a három sor olyan eseménykezelő funkció, amely a Shopify kosárának megfelelő működéséhez szükséges.

"De mi lenne a kocsi állapotával??"

Kérdezheti; vagy:

"Mi lenne, ha meghatároznánk azokat a rendezvénykezelőket a kocsihoz ??"

Valójában ez jön, de még nem!

Ezután a összetevőt hozzáfűzheti a render () függvény aljára, a div. Vége előtt.

Véleményem szerint a kosárnak az alkalmazás bárhonnan elérhetőnek kell lennie. Úgy gondolom, hogy van értelme a összetevőt beletenni az alkalmazás gyökérkomponensébe - más szóval, App.js:

Visszatérés (
... );

Még egyszer, a kosárhoz még nem adtam hozzá kódot az eseménykezelőkhöz. Ezenkívül nem foglalkoztam azzal, hogy az App.js nem tartalmaz a kosárhoz állami elemeket.

Ennek jó oka van.

Körülbelül a projekt felénél rájöttem, hogy a termékkomponens természetesen nincs az App.js fájlban.

Ehelyett három gyermek alkotóelemet temettek el.

Tehát ahelyett, hogy a termékeket három szinttel továbbadná a gyermekeknek, majd a funkciókezelőket egészen a biztonsági mentésig ...

Úgy döntöttem, hogy használok ...

Redux !!!

Huh! Tudom, tudom, hogy Redux, bár nem nagyon nehéz, fáj a% * $ -on! kezdetben az összes szükséges kazánlap bekötéséhez. De ha Ön fejlesztő egy e-kereskedelemmel foglalkozó üzletnél vagy egy e-kereskedelmi bolt tulajdonosa, gondoljon erre a következőkre: A Redux lehetővé teszi a kosár állapotának elérését a weboldalunkon vagy az webapp bármely elemén vagy oldalán.

Ez a képesség nélkülözhetetlen, ha a Siren Apparel bővül, és további termékeket fejlesztünk ki. Ahogy további termékeket készítünk, elkészítek egy külön dedikált áruház oldalt az összes termékkel, miközben csak egy marék kiemelt terméket hagyok a honlapon.

A kosárhoz való hozzáférés elengedhetetlen, ha egy felhasználó egy kicsit körülnéz, elolvassa néhány történetet vagy információt a Siren Apparelról, majd úgy dönt, hogy pénzt fizet. Nem számít, mennyire navigálnak körül, a kosárjukból semmi nem veszik el!

Tehát röviden úgy döntöttem, hogy valószínűleg jobb a Redux bevezetése most, míg webhelyünk kódbázisa nem túl nagy.

A Redux megvalósítása a Shopify számára. SDK vásárlása minimális kazánlemezzel

Telepítse az NPM redux és react-redux csomagokat:

npm install - mentés redux react-redux

Az index.js alkalmazásban importálja a Szolgáltatót a react-redux-ből és a boltját a ./store-ből:

importáljon {szolgáltatót} a 'react-redux'-ből;
import áruház a..-áruházból;

Tekerje be a összetevőt az átadott tárolóval az körül az index.jsto alkalmazásba, és csatlakoztassa az alkalmazást a Redux áruházához:

ReactDOM.render (

    
      
    
 
document.getElementById ( 'root')
);

(Vegye figyelembe, hogy van egy -em is, de ez egy másik bejegyzésben található arról, hogy miként alkalmaztam a nemzetközivé válást és a lokalizációt a Siren Apparel webhelyén a tartalom dinamikus megjelenítéséhez. Más történet egy másik napra.)

Most természetesen még nem készítettünk egy ./store.js fájlt. Hozza létre a boltját a store.js fájlban az src / root fájlban, és tegye ezt be:

importáljon {createStore} a 'redux' -ből;
behozatali reduktor a „./reducers/cart” -ból;
export alapértelmezett createStore (reduktor);

Hozza létre a reduktorfájlt az src / reduktorok / cart.js mappába, és illessze be a következő kódot:

// kezdeti állapot
const initState = {
  isCartOpen: false,
  pénztár: {lineItems: []},
  Termékek: [],
  üzlet: {}
}
// műveletek
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'
// reduktorok
alapértelmezett exportálás (állapot = initState, művelet) => {
  kapcsoló (action.type) {
    ügy CLIENT_CREATED:
      visszatérés {... állam, ügyfél: action.payload}
    eset PRODUCTS_FOUND:
      visszatérés {... állam, termékek: action.payload}
    eset CHECKOUT_FOUND:
      visszatérés {... állam, pénztár: action.payload}
    eset SHOP_FOUND:
      visszatérés {... állam, üzlet: action.payload}
    ADD_VARIANT_TO_CART eset:
      visszatérés {... state, isCartOpen: action.payload.isCartOpen, checkout: action.payload.checkout}
    eset UPDATE_QUANTITY_IN_CART:
      visszatérés {... állam, pénztár: action.payload.checkout}
    eset REMOVE_LINE_ITEM_IN_CART:
      visszatérés {... állam, pénztár: action.payload.checkout}
    OPEN_CART eset:
      return {... state, isCartOpen: true}
    eset CLOSE_CART:
      return {... state, isCartOpen: false}
    alapértelmezett:
      visszatérési állapot
  }
}

Ne aggódjon, nem fogom csak ezt a nagy reduktorot elküldeni, és nem vitatom meg, mi folyik; minden eseményre eljutunk! Itt van néhány szempont, amelyet érdemes megjegyezni.

A kiindulási állapotot abból az állapotból vesszük, amit az állam megírt, mint a Shopify GitHub példában, és betesszük az initState-be, azaz az állam következő négy részébe:

isCartOpen: false,
pénztár: {lineItems: []},
Termékek: [],
üzlet: {}

Végrehajtásom során az állam ügyfélrészét is létrehozom. Felhívom a createClient () függvényt egyszer, majd azonnal beállítom a redux állapotba az index.js-ben. Tehát menjünk az index.js-be:

Vissza az index.js oldalra

const kliens = Client.buildClient ({
  storefrontAccessToken: 'your-shopify-token',
  domain: 'your-shopify-url.myshopify.com'
});
store.dispatch ({típus: 'CLIENT_CREATED', hasznos teher: kliens});

A Shopify SDK vásárlási példájában néhány aszinkron hívás található a termékekkel kapcsolatos információk megszerzése és az információk tárolása érdekében a React komponentWillMount () függvényében. A példakód így néz ki:

komponentWillMount () {
    this.props.client.checkout.create (), majd ((res) => {
      this.setState ({
        pénztár: res,
      });
    });
this.props.client.product.fetchAll ()., majd ((res) => {
      this.setState ({
        termékek: res,
      });
    });
this.props.client.shop.fetchInfo (). majd ((res) => {
      this.setState ({
        üzlet: res,
      });
    });
  }

Ehelyett úgy döntöttem, hogy a lehető legteljesebben, a webhely betöltése után, közvetlenül az index.js-ben csinálom. Ezután kiadtam egy megfelelő eseményt, amikor a válasz minden része megérkezett:

// buildClient () szinkron, így ezeket utána felhívhatjuk!
client.product.fetchAll ()., majd ((res) => {
  store.dispatch ({típus: 'PRODUCTS_FOUND', hasznos teher: res});
});
client.checkout.create (). majd ((res) => {
  store.dispatch ({típus: 'CHECKOUT_FOUND', hasznos teher: res});
});
client.shop.fetchInfo (). majd ((res) => {
  store.dispatch ({típus: 'SHOP_FOUND', hasznos teher: res});
});

Mostanra a reduktor létrejött, és a Shopify API kliens inicializálása az index.js összes elemét befejezte.

Vissza az App.js oldalra

Most az App.js-ben csatlakoztassa a Redux áruházát az App állapotba:

importáljon {connect} a 'react-redux' -ből;

és ne felejtsd el importálni a boltot is:

import áruház a..-áruházból;

Az alapértelmezett alkalmazás exportálásának alján módosítsa erre a következőt:

export alapértelmezett connect ((állapot) => állapot) (App);

Ez összekapcsolja a Redux állapotot az alkalmazás összetevőjével.

Most a render () függvényben hozzáférhetünk a Redux állapotához a Redux getState () -ával (amint azt a vanília react this.state-jának használják):

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

Végül: az eseménykezelők (továbbra is az App.js-ben vagyunk)

Fentiekből Ön tudja, hogy csak három eseménykezelőre van szükségünk az App.js-ben, mivel a kosár csak háromot használ: updateQuantityInCart, removeLineItemInCart és handleCartClose. A GitHub példa-tároló eredeti kosár eseménykezelői, amelyek a helyi összetevők állapotát használják, így néztek ki:

updateQuantityInCart (lineItemId, mennyiség) {
  const checkoutId = this.state.checkout.id
  const lineItemsToUpdate = [{id: lineItemId, mennyiség: parseInt (mennyiség, 10)}]
adja vissza ezt a.props.client.checkout.updateLineItems (checkoutId, lineItemsToUpdate) elemet. majd (res => {
    this.setState ({
      pénztár: res,
    });
  });
}
removeLineItemInCart (lineItemId) {
  const checkoutId = this.state.checkout.id
adja vissza ezt.props.client.checkout.removeLineItems (checkoutId, [lineItemId]), majd (res => {
    this.setState ({
      pénztár: res,
    });
  });
}
handleCartClose () {
  this.setState ({
    isCartOpen: false,
  });
}

Reagálhatjuk őket, hogy az eseményeket a következőképpen küldjük el a Redux üzletbe:

updateQuantityInCart (lineItemId, mennyiség) {
    const state = store.getState (); // állam a redux boltból
    const checkoutId = state.checkout.id
    const lineItemsToUpdate = [{id: lineItemId, mennyiség: parseInt (mennyiség, 10)}]
    state.client.checkout.updateLineItems (checkoutId, lineItemsToUpdate). majd (res => {
      store.dispatch ({típus: 'UPDATE_QUANTITY_IN_CART', hasznos teher: {pénztár: res}});
    });
}
removeLineItemInCart (lineItemId) {
    const state = store.getState (); // állam a redux boltból
    const checkoutId = state.checkout.id
    state.client.checkout.removeLineItems (checkoutId, [lineItemId]), majd (res => {
      store.dispatch ({típus: 'REMOVE_LINE_ITEM_IN_CART', hasznos teher: {pénztár: res}});
    });
}
handleCartClose () {
    store.dispatch ({type: 'CLOSE_CART'});
}
handleCartOpen () {
    store.dispatch ({type: 'OPEN_CART'});
}

Ha követtétek, már említettem, hogy hozzáadtam a saját handleCartOpen funkcióomat, mivel ezt a funkciót propként átadom a