Skip to content

Earth-Hominid/Chair-Mart

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

97 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Chair-Mart

React React Router Jest

A furniture store mock-up featuring a shopping-cart. The app is built with React and utilizes both the React-Router and the React Testing Library. Unit tests were created with Jest. React Styled-Components were implemented for the CSS.

The live version can be found here.

Screen Shot 2022-05-09 at 6 05 29 PM

Features

  • Written with modern React, functional components with hooks
  • Simple React state managment, (no usage of redux, mobx etc)
  • Simple project structure, easy to understand

add-to-cart

detail

Install

git clone https://github.com/Earth-Hominid/chair-mart.git
cd shopping-cart
npm install
npm start

Testing

Unit tests were built with Jest.

Learned: React-Router 6 relies on React context to work, thus, when testing components that use Router components (such as Link, Route, useNavigate etc.), you need to wrap your test component in one of the Router components.

I used BrowserRouter in my RouteSwitch file, thus, my unit tests require:

it('renders logo link', () => {
  render(
    <BrowserRouter>
      <Navigation />
    </BrowserRouter>
  );
  const linkElement = screen.getByAltText(/chair-mart logo/i);
  expect(linkElement).toBeInTheDocument();
});

Technology

  • React React Router
  • JavaScript HTML5 CSS3
  • Adobe XD ESLint Webpack

Favorite Discoveries

One technique I learned was being able to simply insert the Navigation Component above the Router paths, and the navigation bar would be added to all of the pages.

Pior to this, I built all of the pages with the Navigation bar being imported into the component page:

import Nav from '../../navigation/Nav';
import AirlieSection from './AirlieSection';
import Footer from '../../footer/Footer';

const AirliePage = () => {
  return (
    <>
      <Nav />
      <AirlieSection />
      <Footer />
    </>
  );
};

export default AirliePage;

After refactoring the Route Switch file:

import Nav from './components/navigation/Nav';

const RouteSwitch = () => {
  return (
    <BrowserRouter>
      <Nav />
      <UserCart.Provider value="hello from UserCart">
        <Routes>
          <Route path="/" element={<App />} />
          <Route path="/landing" element={<Landing />} />
          <Route path="/Airlie" element={<Airlie />} />
        </Routes>
      </UserCart.Provider>
    </BrowserRouter>
  );
};

This allowed me to pass my shopping-cart object (holding the users cart 'state' info ) into my Navigation component which is now available to every page.

I learned the Outlet Hook from React Router 6, which allowed me to have a standard navigation bar for all of my pages, except on the checkout page. I made two separate components, one with the Nav component and Outlet, and one without the Nav component:

import { Outlet } from 'react-router';

const WithNav = () => {
  return (
    <>
      <Nav />
      <Outlet />
    </>
  );
};

const WithOutNav = () => {
  return (
    <>
      <Outlet />
    </>
  );
};

I was then able to import these into my router app, and the elements in a Route with either component:

return (
    <BrowserRouter>
      <UserCart.Provider value={{ cart, setCart }}>
        <Routes>
          <Route element={<WithOutNav />}>
            <Route path="/Checkout" element={<Checkout />} />
          </Route>
          <Route element={<WithNav />}>
            <Route path="/" element={<App />} />
          </Route>
        </Routes>
      </UserCart.Provider>
    </BrowserRouter>

Aha moments

I was using useEffect, with an empty [], when trying to dynamically update the shopping cart icon and the cart product page.

When the cart is empty, the icon should only show a bag and the cart product page needs to show 'cart is empty'. When the user adds a product to the cart or clears the cart, the bag icon needs to show the quantity of items in the cart, and the cart page needs to show the products.

Using useEffect, only showed the updated values when I clicked refresh on the page.

In order to get the values to appear immediately, I made functions which updated the state, I added these into useContext, and called these changes whenever a button was clicked.

const [bagFilled, setBagFilled] = useState();

const checkBagQuantity = () => {
  if (cart.length <= 0) {
    setBagFilled(false);
  } else if (cart.length > 0) {
    setBagFilled(!bagFilled);
  }
};

I added the checkBagQuantity() inside the functions which dealt with either adding or removing products from the cart. This allowed my cart icon and cart page to dynamically render whenever a product was added or removed, or the cart was cleared.

License

This project is licensed under the [MIT] License - see the LICENSE.md file for details

Acknowledgments

Releases

No releases published

Packages

No packages published

Languages