25
loading...
This website collects cookies to deliver better user experience
npx create-react-app react-ecommerce-butter
cd react-ecommerce-butter
npm start
npm start
, will start the React development server on your system's port 3000. Head over to http://localhost:3000/ in your browser to view your React app.npm i @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4 react-icons
src/index.js
to wrap your react app with the ChakraProvider
component.import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { ChakraProvider } from "@chakra-ui/react";
ReactDOM.render(
<React.StrictMode>
<ChakraProvider>
<App />
</ChakraProvider>
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
.env
file to store ButterCMS and Snipcart API keys securely as environment variables. Run the following command to create the .env
file.touch .env
.env
file as shown below.REACT_APP_BUTTER_ECOMMERCE=''
REACT_APP_SNIPCART_KEY=''
id
- Type: Number
- isRequired
name
- Type: Short Text
- isRequired
description
- Type: Long Text
- isRequired
price
- Type: Number
- isRequired
image
- Type: Media
- isRequired
cookies
, and hit Save as a Collection.cookies
collection. You can either copy the dummy data from https://yakscythe-49dgnn.stormkit.dev/ or add your favorite cookies.cookies
collection will look after adding products to it.buttercms
library to fetch data from ButterCMS. Run the following command in your project's root directory to install buttercms
.npm i buttercms
App.js
file with the following code.import { useState, useEffect } from "react";
import Butter from "buttercms";
const butter = Butter(process.env.REACT_APP_BUTTER_ECOMMERCE);
function App() {
const [products, setProducts] = useState([]);
useEffect(() => {
async function fetchData() {
const res = await butter.content.retrieve(["cookies"], {
order: "name",
});
const { data } = await res.data;
const allProducts = data.cookies;
setProducts(allProducts);
}
fetchData();
}, []);
return (
<div>
{products.map((product) => (
<div>
<img src={product.image} alt={`${product.name}`} />
{product.name}
{product.price}
{product.description}
</div>
))}
</div>
);
}
export default App;
Butter
using your ButterCMS API key stored in .env
file and accessed using process.env.REACT_APP_BUTTER_ECOMMERCE
. products
to store the data fetched from ButterCMS using the useState()
hook. Hooks are functions that use React features like defining a state without writing a class.cookies
using butter's .retrieve()
method inside the React's useEffect()
hook.products
state using the setProducts()
method. Here is how the state products
look like.[
{
"meta": {
"id": 125151
},
"id": "1",
"name": "Biscotti Cookies",
"price": 40,
"description": "Biscotti actually means “twice baked” and the cookie is indeed baked twice, resulting in its hard and crunchy texture.",
"image": "https://cdn.buttercms.com/UqbFGAJLTGqtYqF2UajV"
},
{
"meta": {
"id": 113778
},
"id": "2",
"name": "Chocolate Chip Cookies",
"price": 30,
"description": "Chocolate chip cookies are the perennial classic and longtime fan favorite. ",
"image": "https://cdn.buttercms.com/Xe1zfNvRCiOOI4LPuoVb"
}
]
products
state using the .map()
method and display the data on the page using curly brackets {}
.{
products.map((product) => (
<div>
<img src={product.image} alt={`${product.name}`} />
{product.name}
{product.price}
{product.description}
</div>
))
}
App.js
with Chakra UI components to style your ecommerce app.import {
Container,
Text,
Divider,
Box,
Image,
Button,
SimpleGrid,
Flex,
} from "@chakra-ui/react";
import { FiShoppingCart, FiShoppingBag } from "react-icons/fi";
import { useState, useEffect } from "react";
import Butter from "buttercms";
const butter = Butter(process.env.REACT_APP_BUTTER_ECOMMERCE);
function App() {
const [products, setProducts] = useState([]);
useEffect(() => {
async function fetchData() {
const res = await butter.content.retrieve(["cookies"], {
order: "name",
});
const { data } = await res.data;
const allProducts = data.cookies;
setProducts(allProducts);
}
fetchData();
}, []);
return (
<Container maxW="container.xl" h="100vh" >
<Flex justifyContent="space-between" alignContent="center">
<Text
as="a"
href="/"
fontSize="2rem"
color="gray.900"
fontFamily="Robo"
my="5px"
>
Cookie Jar
</Text>
<Button
my="5px"
colorScheme="green"
variant="ghost"
leftIcon={<FiShoppingBag size="24px" />}
size="lg"
p={2}
>
View Cart
</Button>
</Flex>
<Divider />
<Box mt={4}>
<SimpleGrid
minChildWidth="300px"
align="center"
justify="center"
spacing="40px"
mb={32}
>
{products.map((product) => (
<Box
bg="white"
maxW="sm"
borderWidth="1px"
rounded="lg"
shadow="lg"
_hover={{ shadow: "dark-lg" }}
key={product.id}
>
<Image
h="350px"
fit="cover"
src={product.image}
alt={`Picture of ${product.name}`}
roundedTop="lg"
/>
<Box p="6">
<Flex
mt="1"
justifyContent="space-between"
alignContent="center"
>
<Text
fontSize="2xl"
fontWeight="semibold"
as="h4"
textTransform="uppercase"
lineHeight="tight"
fontFamily="Roboto"
>
{product.name}
</Text>
<Text
as="h4"
fontSize="2xl"
fontWeight="bold"
color="teal.600"
>
${product.price}
</Text>
</Flex>
<Text
mt={2}
color="gray.500"
display={{ base: "none", md: "flex" }}
>
{product.description}
</Text>
<Button
leftIcon={<FiShoppingCart size="24px" />}
size="lg"
mt={4}
isFullWidth
colorScheme="blue"
variant="outline"
alignSelf={"center"}
>
Add to Cart
</Button>
</Box>
</Box>
))}
</SimpleGrid>
</Box>
</Container>
);
}
export default App;
Container
, Flex
, etc., and use them to style your app. Except for styling, the code used to fetch and display the data on the app remains the same.View Cart
, which shows users their cart, and Add to Cart
, which adds the product to the cart. These buttons don't work yet; you will integrate them with Snipcart in the next section.public/index.html
file and add the following code inside the <Head>
tag.<link rel="preconnect" href="https://app.snipcart.com">
<link rel="preconnect" href="https://cdn.snipcart.com">
<link rel="stylesheet" href="https://cdn.snipcart.com/themes/v3.2.0/default/snipcart.css"/>
public/index.html
before closing <Body>
tag.<script
async
src="https://cdn.snipcart.com/themes/v3.2.0/default/snipcart.js"
></script>
<div
id="snipcart"
data-config-modal-style="side"
data-api-key="%REACT_APP_SNIPCART_KEY%"
hidden
></div>
.env
file is being accessed in the above code using %REACT_APP_SNIPCART_KEY%
. Add to Cart
button in src/App.js
like this.<Button
leftIcon={<FiShoppingCart size="24px" />}
size="lg"
mt={4}
isFullWidth
colorScheme="blue"
variant="outline"
alignSelf={"center"}
className="snipcart-add-item"
data-item-id={product.id}
data-item-image={product.image}
data-item-name={product.name}
data-item-url="/"
data-item-description={product.description}
data-item-price={product.price}
>
Add to Cart
</Button>
Add to Cart
button in action.View Cart
button like with className="snipcart-checkout"
.<Button
my="5px"
colorScheme="green"
variant="ghost"
leftIcon={<FiShoppingBag size="24px" />}
size="lg"
p={2}
className="snipcart-checkout"
>
View Cart
</Button>
git add .
git commit -m"Finished building the React Ecommerce app"
react-ecommerce-butter
as the repo name. You can skip other fields for now. Finally, click on the Create repository
button....or push an existing repository from the command line
section.git remote add origin https://github.com/lelouchB/react-ecommerce-butter.git
git branch -M main
git push -u origin main
react-ecommerce-butter
repo. react-ecommerce-butter
repository and proceed further.production
environment. You can create as many environments as you want. In this tutorial, we will deploy using the default production
environment.production
environment; else your deployment will fail. production
environment.Edit
button or the pencil icon to edit the environment configurations.build
under Public folder field and add npm run build
command under Build command field.REACT_APP_BUTTER_ECOMMERCE
and REACT_APP_SNIPCART_KEY
environment variables with their values and click on the Update environment button.Finished building the React Ecommerce app
.