React Native is a cross-platform cellular app framework that means that you can construct native cellular functions for iOS and Android utilizing JavaScript. It was developed by Meta Platforms, Inc. and it’s at the moment among the many hottest JavaScript frameworks with an enormous lively neighborhood behind it.

Medusa is an open supply headless commerce platform that means that you can create shops in a couple of minutes. It consists of each characteristic a retailer wants similar to order administration, clients, funds, merchandise, reductions, and much more.

On this tutorial, you might be constructing a React Native ecommerce cellular software with Medusa. For this half, you’re going to create two screens, one for all merchandise and the opposite for the product information.

You can too discover the supply code of the applying on the GitHub

Demo App



Stipulations

Earlier than you begin with the tutorial ensure you have Node.js v14 or better put in in your machine.



Set Up Medusa Server

Step one is to setup the Medusa server, the place the backend and APIs are dealt with.

You’ll be able to set up the Medusa CLI in your machine by operating the next command:

npm set up -g @medusajs/medusa-cli
Enter fullscreen modeExit fullscreen mode

As soon as the CLI is put in efficiently, run the next command to create a Medusa challenge:

medusa new my-medusa-store --seed
Enter fullscreen modeExit fullscreen mode

The --seed possibility is used so as to add dummy knowledge similar to merchandise and customers to the shop.

Change to the newly-created listing my-medusa-store and run the next command to begin the medusa server:

npm begin
Enter fullscreen modeExit fullscreen mode

It is suggested so as to add a storage plugin to have the ability to add merchandise with photos in Medusa. You should use MinIO, AWS S3, or Spaces.



Set Up Medusa Admin

Medusa has a really highly effective admin dashboard the place you’ll be able to handle your merchandise, funds, transaction, and extra. That is very straightforward to setup nonetheless it’s non-compulsory, so in order for you you’ll be able to skip this part.

In a separate listing, clone the Medusa Admin:

 git clone https://github.com/medusajs/admin medusa-admin
Enter fullscreen modeExit fullscreen mode

As soon as it’s cloned, you must see a brand new listing named medusa-admin. Navigate to the brand new listing and run the next command to put in the dependencies of the challenge:

npm set up
Enter fullscreen modeExit fullscreen mode

Lastly, ensure that the Medusa server remains to be operating and begin the admin panel server by operating the next command:

npm run develop
Enter fullscreen modeExit fullscreen mode

Now, open your browser and navigate to localhost:7000 and you must see the login web page for admin panel. Login in to the admin with the under credentials.

The --seed possibility you used earlier provides an admin person with the e-mail and password

As soon as you might be logged in efficiently, select Merchandise from sidebar and you must see the record of merchandise in your retailer.

In case you are experiencing connection points, it is most certainly due to CORS points. Examine here the best way to repair it.

Products on Admin

You can too create a brand new product by clicking on the “New Product” button. Add info on your product similar to a reputation, description, deal with, variants, photos, costs, and much more.

Product Form



Set Up React Native Ecommerce Venture

Now that you’ve got the shop backend and admin panel prepared it’s time to begin engaged on the react native ecommerce app.

On this tutorial, you might be utilizing Expo CLI to construct the app. Run the next command to put in the Expo CLI:

npm set up -g expo-cli
Enter fullscreen modeExit fullscreen mode

As soon as the CLI is put in efficiently, run the next command to create a brand new react native ecommerce challenge:

expo init
Enter fullscreen modeExit fullscreen mode

You may be promoted with some questions. You’ll be able to observe the under code for the solutions:

What would you want to call your app? … medusa-store
Select a template: › clean a minimal app as clear as an empty canvas
Downloaded template.

🧶 Utilizing Yarn to set up packages. Move --npm to make use of npm as a substitute.
Put in JavaScript dependencies.

✅ Your challenge is prepared!

To run your challenge, navigate to the listing and run one of many following yarn instructions.

- cd medusa-store
- yarn begin # you'll be able to open iOS, Android, or web from right here, or run them immediately with the instructions under.
- yarn android
- yarn ios
- yarn web
Enter fullscreen modeExit fullscreen mode

As soon as the challenge is created efficiently you must see a brand new listing named medusa-store. Navigate to the brand new listing and run the next command to put in a couple of different dependencies:

expo set up react-native-screens react-native-router-flux react-native-reanimated rn-responsive-screen react-native-safe-area-context @expo/vector-icons react-native-gesture-handler axios
Enter fullscreen modeExit fullscreen mode
  • react-native-screens is used to reveal native navigation container parts to React Native.
  • react-native-router-flux supplies API that helps customers navigate between screens.
  • react-native-reanimated creates clean animations and interactions that run on the UI thread.
  • rn-responsive-screen is a small package deal used for responsiveness within the app.
  • react-native-safe-area-context is a versatile method to deal with secure areas.
  • react-native-gesture-handler supplies native-driven gesture administration APIs for constructing the absolute best touch-based experiences.
  • axios is a promise-based HTTP Shopper to simply ship requests to REST APIs and carry out CRUD operations.
  • @expo/vector-icons consists of well-liked icons units which you should utilize within the app.

After the packages are put in efficiently, begin the development server by operating the next:

expo begin
Enter fullscreen modeExit fullscreen mode

You’ll be able to both scan the QR code utilizing your gadget or run the app on an Android/iOS simulator. As soon as the app is proven in your cellular, you must see the same display.

New App Screen

This can be a primary react native code within the App.js file.



Set Up Routes

On this part, you’ll arrange completely different routes in your app.

Earlier than establishing the routes, you must create a couple of screens. Create a brand new folder named screensand inside it create a brand new file named Merchandise.js.

Inside Merchandise.js insert the next code:

import { StyleSheet, Textual content, View } from "react-native";

export default operate Merchandise() {
  return (
    <View fashion={types.container}>
      <Textual content>Product Display screen!</Textual content>
    </View>
  );
}

const types = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "middle",
    justifyContent: "middle",
  },
});
Enter fullscreen modeExit fullscreen mode

For now it incorporates a quite simple Textual content element.

Now that you’ve got a display setup, you’ll be able to proceed so as to add routes to the challenge. Exchange the code inside the App.js with the next:

import { Router, Scene, Stack } from "react-native-router-flux";
import Merchandise from "./screens/Merchandise";

export default operate App() {
  return (
    <Router>
      <Stack key="root">
        <Scene key="merchandise" element={Merchandise} hideNavBar />
      </Stack>
    </Router>
  );
}
Enter fullscreen modeExit fullscreen mode

Within the above code, you might be utilizing react-native-router-flux to create the navigation. Router is used as a mum or dad element and every Scene represents one display. For now you’ve gotten only one display.

Save the file and also you would possibly see an error just like this.

Error: Requiring module "node_modules/react-native-reanimated/src/Animated.js", which threw an exception: Error: Reanimated 2 failed to create a worklet, possibly you forgot to add Reanimated's babel plugin?
Enter fullscreen modeExit fullscreen mode

It’s as a result of that react-native-router-flux makes use of react-native-reanimated and as a way to make it work it’s essential add it to babel.config.js. Open the babel file out of your listing and add the under line after presents:

plugins: ["react-native-reanimated/plugin"],
Enter fullscreen modeExit fullscreen mode

Save the file and restart the server with the next command:

expo begin -c
Enter fullscreen modeExit fullscreen mode

The choice -c clears the cache earlier than operating the server.

If you happen to see the error “Invariant Violation: Tried to register two views with the identical identify RNGestureHandlerButton”, delete the node_modules listing and use Yarn to re-install the dependencies.



Merchandise Checklist Display screen

Create a brand new folder within the root listing named parts. Within the parts folder create 3 recordsdata. Button.js, ProductCard.js, and Header.js.

Within the Button.js file insert the next code to create a primary button element:

import { View, Textual content, StyleSheet } from "react-native";
import React from "react";
import { widthToDp } from "rn-responsive-screen";

export default operate Button({ title, onPress, fashion, textSize }) {
  return (
    <View fashion={[styles.container, style]}>
      <Textual content
        fashion={[styles.text, { fontSize: textSize ? textSize : widthToDp(3.5) }, ]}
        onPress={onPress}
      >
        {title}
      </Textual content>
    </View>
  );
}

const types = StyleSheet.create({
  container: {
    backgroundColor: "#C37AFF",
    padding: 5,
    width: widthToDp(20),
    alignItems: "middle",
    justifyContent: "middle",
    borderRadius: 59,
  },
  textual content: {
    shade: "#fff",
    fontWeight: "daring",
  },
});
Enter fullscreen modeExit fullscreen mode

Equally within the Header.js insert the next code to create a easy header element:

import { View, Picture, StyleSheet, Textual content } from "react-native";
import React from "react";

export default operate Header({ title }) {
  return (
    <View fashion={types.container}>
      <Picture
        supply={{
          uri: "https://user-images.githubusercontent.com/7554214/153162406-bf8fd16f-aa98-4604-b87b-e13ab4baf604.png",
        }}
        fashion={types.brand}
      />
      <Textual content fashion={types.title}>{title}</Textual content>
    </View>
  );
}
const types = StyleSheet.create({
  container: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "middle",
    marginBottom: 10,
  },
  title: {
    fontSize: 20,
    fontWeight: "500",
  },
  brand: {
    width: 50,
    peak: 50,
  },
});
Enter fullscreen modeExit fullscreen mode

The final one is ProductCard.js. It’s the fundamental element wherein you render the product knowledge:

import { View, Textual content, Picture, StyleSheet } from "react-native";
import React from "react";
import { widthToDp, heightToDp } from "rn-responsive-screen";
import Button from "./Button";

export default operate ProductCard({ key, product }) {
  return (
    <View fashion={types.container} key={key}>
      <Picture
        supply={{
          uri: product.thumbnail,
        }}
        fashion={types.picture}
      />
      <Textual content fashion={types.title}>{product.title}</Textual content>
      <Textual content fashion={types.class}>{product.deal with}</Textual content>
      <View fashion={types.priceContainer}>
        <Textual content fashion={types.value}>
          ${product.variants[0].costs[1].quantity / 100}
        </Textual content>

        <Button
          title="BUY"
        />
      </View>
    </View>
  );
}

const types = StyleSheet.create({
  container: {
    shadowColor: "#000",
    borderRadius: 10,
    marginBottom: heightToDp(4),
    shadowOffset: {
      width: 2,
      peak: 5,
    },
    shadowOpacity: 0.25,
    shadowRadius: 6.84,
    elevation: 5,
    padding: 10,
    width: widthToDp(42),
    backgroundColor: "#fff",
  },
  picture: {
    peak: heightToDp(40),
    borderRadius: 7,
    marginBottom: heightToDp(2),
  },
  title: {
    fontSize: widthToDp(3.7),
    fontWeight: "daring",
  },
  priceContainer: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "middle",
    marginTop: heightToDp(3),
  },
  class: {
    fontSize: widthToDp(3.4),
    shade: "#828282",
    marginTop: 3,
  },
  value: {
    fontSize: widthToDp(4),
    fontWeight: "daring",
  },
});
Enter fullscreen modeExit fullscreen mode

Within the above code, the product value is split by 100 as a result of in Medusa the costs are hosted on the server with out decimals.

Create a brand new folder named constants and inside it create a brand new file named url.js with the next content material:

const baseURL = "http://127.0.0.1:9000";

export default baseURL;
Enter fullscreen modeExit fullscreen mode

Within the above code, you outline your Medusa server’s base URL. To have the ability to join out of your gadget to the native server, it’s essential to change the worth of baseURL to your machine’s IP handle. You’ll be able to confer with this guide to learn to discover your IP handle.

That’s it for the parts. Now change the code within the Merchandise.js with the next:

import { ScrollView, StyleSheet,TouchableOpacity, View } from "react-native";
import React, { useEffect, useState } from "react";
import ProductCard from "../parts/ProductCard";
import { widthToDp } from "rn-responsive-screen";
import axios from "axios";
import Header from "../parts/Header";
import { Actions } from "react-native-router-flux";
import baseURL from "../constants/url";

export default operate Merchandise() {
  const [products, setProducts] = useState([]);

  operate fetchProducts() {
        axios.get(`${baseURL}/retailer/merchandise`).then((res) => {
      setProducts(res.knowledge.merchandise);
    }); 
 }

  useEffect(() => {
    fetchProducts();
  }, []);

  return (
    <View fashion={types.container}>
      <Header title="Medusa's Retailer" />
      <ScrollView>
        <View fashion={types.merchandise}>
          {merchandise.map((product) => (
            <ProductCard key={product.id} product={product} />
          ))}
        </View>
      </ScrollView>
    </View>
  );
}

const types = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 50,
    backgroundColor: "#fff",
    alignItems: "middle",
    justifyContent: "middle",
  },
  merchandise: {
    flex: 1,
    flexDirection: "row",
    flexWrap: "wrap",
    width: widthToDp(100),
    paddingHorizontal: widthToDp(4),
    justifyContent: "space-between",
  },
});
Enter fullscreen modeExit fullscreen mode

Within the code above, you name fetchProducts when the display masses utilizing useEffect. Within the fetchProducts operate, you utilize axios to fetch the products from the Medusa server and reserve it within the state.

When you fetch the merchandise, you render them utilizing the ProductCard element.

Save the file and ensure that Expo and the Medusa server are operating. Then, open the app in your gadget and you must see on the house display the merchandise out of your Medusa server.

Home Screen



Product Data Display screen

On this part, you’ll create the Product Data display the place the person can see extra particulars in regards to the product.

Within the screens listing, create a brand new file named ProductInfo.js and for now you should utilize it to render a easy Textual content element:

import { View, Textual content } from "react-native";
import React from "react";

export default operate ProductInfo() {
  return (
    <View>
      <Textual content>Product Data Display screen</Textual content>
    </View>
  );
}
Enter fullscreen modeExit fullscreen mode

Then, add the import ProductInfo on the prime of App.js:

import ProductInfo from "./screens/ProductInfo";
Enter fullscreen modeExit fullscreen mode

And add a brand new Scene element under the prevailing Scene element within the returned JSX:

<Scene key="ProductInfo" element={ProductInfo} hideNavBar />
Enter fullscreen modeExit fullscreen mode

Within the parts listing, create a brand new listing named ProductInfo and create inside it Picture.js with the next content material:

import { View, TouchableOpacity, Picture, StyleSheet } from "react-native";
import React, { useEffect, useState } from "react";
import { widthToDp } from "rn-responsive-screen";

export default operate Photographs({ photos }) {
  const [activeImage, setActiveImage] = useState(null);

  useEffect(() => {
    setActiveImage(photos[0].url);
  }, []);

  return (
    <View fashion={types.imageContainer}>
      <Picture supply={{ uri: activeImage }} fashion={types.picture} />
      <View fashion={types.previewContainer}>
        {photos.map((picture, index) => (
          <TouchableOpacity
            key={index}
            onPress={() => {
              setActiveImage(picture.url);
            }}
          >
            <Picture
              supply={{ uri: picture.url }}
              fashion={[
                styles.imagePreview,
                {
                  borderWidth: activeImage === image.url ? 3 : 0,
                },
              ]}
            />
          </TouchableOpacity>
        ))}
      </View>
    </View>
  );
}

const types = StyleSheet.create({
  picture: {
    width: widthToDp(100),
    peak: widthToDp(100),
  },
  previewContainer: {
    flexDirection: "row",
    justifyContent: "middle",
    alignItems: "middle",
    marginTop: widthToDp(-10),
  },
  imageContainer: {
    backgroundColor: "#F7F6FB",
    paddingBottom: widthToDp(10),
  },
  imagePreview: {
    width: widthToDp(15),
    marginRight: widthToDp(5),
    borderColor: "#C37AFF",
    borderRadius: 10,
    peak: widthToDp(15),
  },
});
Enter fullscreen modeExit fullscreen mode

Within the above element you show a fundamental massive picture and under it the remainder of the product photos as thumbnails. When the person press on one of many thumbnail photos it’s set because the lively picture and displayed as the primary picture.

Within the Merchandise.js file, change the map operate within the returned JSX with the next:

{merchandise.map((product) => (
    <TouchableOpacity key={product.id} onPress={() => Actions.ProductInfo({ productId: product.id })}>
      <ProductCard product={product} />
    </TouchableOpacity>
  ))
}
Enter fullscreen modeExit fullscreen mode

You add a TouchableOpacity that navigates the person to the product information display once they click on on a product.

Utilizing react-router-flux you go the product ID from the house display to the product information display.

Then, change the code in ProductInfo.js with the next:

import { View, Textual content, ScrollView,TouchableOpacity, StyleSheet } from "react-native";
import React, { useState, useEffect } from "react";
import axios from "axios";
import { SafeAreaView } from "react-native-safe-area-context";
import Photographs from "../parts/ProductInfo/Picture";
import baseURL from "../constants/url";
import { Actions } from "react-native-router-flux";
import { Ionicons } from "@expo/vector-icons";

export default operate ProductInfo({ productId }) {
  const [productInfo, setproductInfo] = useState(null);

    useEffect(() => {
    axios.get(`${baseURL}/retailer/merchandise/${productId}`).then((res) => {
      setproductInfo(res.knowledge.product);
    });
  }, []);

  return (
    <SafeAreaView fashion={types.container}>
            <TouchableOpacity onPress={() => Actions.pop()}>
        <Ionicons
          fashion={types.icon}
          identify="arrow-back-outline"
          measurement={24}
          shade="black"
        />
      </TouchableOpacity>
      <ScrollView>
        {productInfo && (
          <View>
            <Photographs photos={productInfo.photos} />
          </View>
        )}
      </ScrollView>
    </SafeAreaView>
  );
}

const types = StyleSheet.create({
container: {
    flex: 1,
    backgroundColor: "#fff",
    justifyContent: "middle",
  },
  icon: {
    marginLeft: 10,
  },
});
Enter fullscreen modeExit fullscreen mode

To briefly clarify the code snippet:

  • First you import all vital parts.
  • Then you definately fetch the product knowledge in useEffect operate and reserve it within the state.
  • Lastly, you show the pictures utilizing the Photographs element.

Open the app now and click on on any product on the house display. A brand new display will open displaying the product’s photos.

Short Product Details

Now, you’ll show the product’s info.

Within the parts folder, contained in the ProductInfo listing create a brand new file named MetaInfo.js with the next content material:

import { View, Textual content, StyleSheet } from "react-native";
import React, { useState } from "react";
import { peak, heightToDp } from "rn-responsive-screen";

export default operate MetaInfo({ product }) {
  const [activeSize, setActiveSize] = useState(0);
  return (
    <View fashion={types.container}>
      <View fashion={types.row}>
        <Textual content fashion={types.title}>{product.title}</Textual content>
        <View>
          <Textual content fashion={types.value}>
            ${product.variants[0].costs[1].quantity / 100}
          </Textual content>
          <Textual content fashion={types.star}>⭐⭐⭐</Textual content>
        </View>
      </View>
      <Textual content fashion={types.heading}>Accessible Sizes</Textual content>
      <View fashion={types.row}>
        {product.choices[0].values.map((measurement, index) => (
          <Textual content
            onPress={() => {
              setActiveSize(index);
            }}
            fashion={[
              styles.sizeTag,
              {
                borderWidth: activeSize === index ? 3 : 0,
              },
            ]}
          >
            {measurement.worth}
          </Textual content>
        ))}
      </View>
      <Textual content fashion={types.heading}>Description</Textual content>
      <Textual content fashion={types.description}>{product.description}</Textual content>
    </View>
  );
}

const types = StyleSheet.create({
  container: {
    marginTop: heightToDp(-5),
    backgroundColor: "#fff",
    borderTopLeftRadius: 20,
    borderTopRightRadius: 20,
    peak: heightToDp(50),
    padding: heightToDp(5),
  },
  title: {
    fontSize: heightToDp(6),
    fontWeight: "daring",
  },
  row: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "middle",
  },
  value: {
    fontSize: heightToDp(5),
    fontWeight: "daring",
    shade: "#C37AFF",
  },
  heading: {
    fontSize: heightToDp(5),
    marginTop: heightToDp(3),
  },
  star: {
    fontSize: heightToDp(3),
    marginTop: heightToDp(1),
  },
  sizeTag: {
    borderColor: "#C37AFF",
    backgroundColor: "#F7F6FB",
    shade: "#000",
    paddingHorizontal: heightToDp(7),
    paddingVertical: heightToDp(2),
    borderRadius: heightToDp(2),
    marginTop: heightToDp(2),
    overflow: "hidden",
    fontSize: heightToDp(4),
    marginBottom: heightToDp(2),
  },
  description: {
    fontSize: heightToDp(4),
    shade: "#aaa",
    marginTop: heightToDp(2),
  },
});
Enter fullscreen modeExit fullscreen mode

Within the above element, you render the product title, value, description and variants.

For the product variant, you map all of the variants and when a person press on one in all them, you set that variant as lively.

Save the MetaInfo.js file and import it on the prime of screens/ProductInfo.js:

import MetaInfo from "../parts/ProductInfo/MetaInfo";
Enter fullscreen modeExit fullscreen mode

Then, within the returned JSX add the MetaInfo element under the Photographs element:

<MetaInfo product={productInfo} />
Enter fullscreen modeExit fullscreen mode

Save the modifications and verify the app now. The product information display now exhibits particulars in regards to the product.

Product Details



What’s Subsequent?

This text provides you the premise to making a Medusa and React Native ecommerce app. Listed here are some extra functionalities you’ll be able to add utilizing Medusa:

  1. Add a cart and allow adding products to cart.
  2. Add a fee supplier utilizing Stripe.
  3. Add a search engine utilizing MeiliSearch.
  4. Take a look at the documentation for what extra you are able to do with Medusa.

Ought to you’ve gotten any points or questions associated to Medusa, then be at liberty to succeed in out to the Medusa group through Discord.



Abu Sayed is the Best Web, Game, XR, Blockchain Developer, Producer and Singer in Bangladesh. Don't forget to Checkout his Latest Songs.
ADS
Watch Free Onlyfans, Patreon, Celebrity Leaked Videos


Read More