Deploy Containers Close to Your Users

This Engineering Education (EngEd) Program is supported by Section.

Instantly deploy containers globally. Section is affordable, simple and powerful.

Get Started for Free.

Getting Started With React Cosmos

September 29, 2021

The React library has quickly established itself as a popular JavaScript UI library. As a component library, developers can build reusable UI components. However, reusing and implementing tests within the components is a complex task.

React Cosmos is a React library that provides an environment to reuse, test, and develop UI components in isolation. Using the React Cosmos sandbox, we can interactively change component props and get instant changes during development.

In this article, we will cover the basics of React Cosmos using a food ordering React application. Let us get started!

Prerequisites

To follow along, you need to have:

The benefits of React Cosmos in React applications

React has revolutionized frontend development forever. As frontend developers, most of our tasks involve crafting clean and functional UIs.

However, ensuring that they will work flawlessly in large applications involves a lot of testing, compatibility support, and more.

To solve this, we need to ensure consistency in design across components.

The key benefits of using React Cosmos include:

  • We can use its Real-time external API mocking for visual regression testing, or even snapshot testing.
  • Debugging is much easier due to isolated components.
  • Using a component-based library like React is essential in design systems. Building components using React Cosmos ensures reusability across multiple projects. This avoids duplication of effort in creating consistent branding across the product suite.

Project setup

To get started with React Cosmos, we will clone an app from this repository. This is a simple food ordering application made using React and tailwind CSS.

Using git on your system, clone our starter code in this repository with the following command:

git clone https://github.com/marienjus/React-Cosmos.git

Once you’ve cloned the repo, install dependencies by running yarn install or npm install in your terminal and open the application in your favorite IDE. Below is the structure of our components in this application.

Our src/components folder has:

  • A simple reusable Button component.
  • A CartCard component that shows details of a cart item.
  • A Checkout component that summarizes the cart, such as total price, sub-total price, and delivery fee.
  • A FoodCard component that displays the details about the food with a button to add the food.

In our src/pages, we have:

  • The cart component page which displays our cart items and the checkout component.
  • The home page component is our landing page. It renders a navbar and the FoodCard component.

Launch the development server with the command below:

yarn start

For npm use:

npm start

The React development server starts at http://localhost:3000/. The application in the browser should look like this:

cosmos landing page

cosmos cart page

Let’s install the React Cosmos package as a dev dependency. On your terminal, execute the command below:

yarn add -D react-cosmos

If you are using npm, run the command below:

 npm i -D react-cosmos

To make sure that React Cosmos works with create-react-app, add a cosmos.config.json file in your project root folder with the code below:

{
	"staticPath": "public",
	"watchDirs": ["src"],
	"webpack": {
		"configPath": "react-scripts/config/webpack.config"
	},
	"globalImports": ["src/styles/main.css"]
}

Here, watchDirs and staticPath properties tell React Cosmos to watch our src directory for any static assets in the public folder.

Finally, We then need to point our webpack config file and use globalImports to enable our CSS global files.

Next, we need to install a cross-env package to resolve React Cosmos and hot reload issues. To install it, run the following command:

yarn add cross-env -D

Or use npm:

npm install cross-env -D

Finally, we need to add the React Cosmos to the scripts part of our package.json file:

  "scripts": {
    "cosmos": "cross-env FAST_REFRESH=false cosmos",
    "cosmos:export": "cross-env FAST_REFRESH=false cosmos-export"
  }

Congratulations! You have now set up React Cosmos. In the following section, we will start using React Cosmos in our React application.

Running React application using React Cosmos

To start the application using the React Cosmos server on your terminal, run the command below:

npm run cosmos

If you prefer yarn:

yarn cosmos

When the server is up and running, navigate to http://localhost/5000 in your favorite browser, and you should see something like this.

cosmos starter

Creating a Component using Fixtures

In React Cosmos, we build components by creating fixtures. Fixtures are files that contain a default export (as either a React Component or React Node).

React cosmos displays the fixtures in a sandbox explorer. Therefore, to enable React Cosmos to track our components, we need to append .fixture to the file names containing it.

To get started, create a file within your src folder and name it Button.fixture.jsx.

Inside the file, import the Button component as:

import Button from "./components/Button/Button";

Then export it as default:

export default (
	<div>
		<div className="w-50 mx-auto">
			<Button>Cosmos</Button>
		</div>
	</div>
);

In our Cosmos Explorer under ALL FIXTURES, we should see:

cosmos button

On the right panel, we can edit any of the button component’s properties. Let’s add a secondary and primary Button variant to a variant prop.

Return to your src/component folder and update the Button.jsx component with the following code:

export default function Button({ children, variant = "primary" }) => {
  return (
    <div>
    <button
      className={`w-full block h-12 ${
        variant === 'primary' ? "bg-black" : "bg-blue-500"
      } hover:opacity-60 rounded-sm mt-3`}
      style={{ color: 'white', border: "none", outline: "none" }}
      type="button"
    >
      {children}
    </button>
    </div>
  )
}

Next, import the fixture feature from react-cosmos and the Button component.

// import useSelect to use enable the selection feature
import { useSelect } from "react-cosmos/fixture";

// Add the Button component to the fixture file
import Button from "./components/Button/Button";

Finally, export the Button component as default in our Buttton.fixtures.js file.

export default () => {
	const [variant] = useSelect("variant", {
		options: ["primary", "secondary"],
	});

	return (
		<div className="w-60 mx-auto">
			<Button variant={variant}>Cosmos</Button>
		</div>
	);
};

Let’s briefly dissect the above code:

Our Button fixture includes a variant prop with a Control panel hook useSelect. We import the useSelect hook to enable us to set options for the variant prop. Therefore, in our sandbox, we can manually select this rather than typing.

Let’s run a demo in the sandbox:

cosmos variants

We can toggle between either of the two variant options. Try changing the variant prop to confirm that our background color changes accordingly.

Creating a fixture for checkout component

Within your src folder, add another file as Checkout.fixture.jsx:

Import the Checkout component from the components/Checkout/Checkout file:

import Checkout from "./components/Checkout/Checkout";

Next, add mock data inside the checkout fixture file and export it as default.

const dummyData = {
	subTotalPrice: 150,
	deliveryFee: 15,
	totalPrice: 165,
};

export default (
	<div className="mx-auto w-50">
		<Checkout
			subTotal={dummyData.subTotalPrice}
			deliveryFee={dummyData.deliveryFee}
			total={dummyData.totalPrice}
		/>
	</div>
);

Click on the left panel under ALL FIXTURE option. Here, we perform any visual tests by passing different prop values to our dummyData object and playing around with it in the sandbox.

Cards fixture

For this fixture, create a Cards.fixture.jsx file within the src folder. Our Cards Fixture exports multiple fixtures as objects with React’s export default keywords.

First, import the CartCard and FoodCard components.

import CartCard from "./components/CartCard/CartCard";
import FoodCard from "./components/FoodCard/FoodCard";
import foodImg from "./images/food1.jpg";

Next, include the food and order objects which will serve as data for the props.

const order = {
	orderId: 1,
	name: "Chicken",
	price: "8.00",
	quantity: 1,
	updateList: () => {},
};

const food = {
	foodId: 2,
	name: "Hot Chicken",
	price: "8.00",
};

Finally, export the FoodCard and CartCard fixtures:

export default {
	FoodCard: (
		<FoodCard
			id={food.foodId}
			name={food.name}
			price={food.price}
			imgSrc={foodImg}
		/>
	),
	CartCard: (
		<CartCard
			id={order.orderId}
			name={order.name}
			price={order.price}
			imgSrc={foodImg}
			quantity={order.quantity}
			updateList={order.updateList}
		/>
	),
};

Our sandbox has a Cards fixture, within it, export CartCard and FoodCard as components.

This makes everything much more organized, especially as the sandbox gets more fixtures.

Static exports

When hosting our fixtures as a component library in any static hosting service like Netlify, React Cosmos allows us to export our fixtures.

Run the command below:

yarn cosmos: export

Or

npm run cosmos: export

The export we perform excludes some available development features to reduce dependencies. However, it will allow you to browse fixtures and play with component inputs as in the development sandbox.

Conclusion

Failing to reuse your components is slowing your development.

React Cosmos improves the developer experience by making it possible to build UI components iteratively and in isolation.

In addition, having features such as snapshot and visual regression testing tailored to our needs makes developers even more productive.

At the time of writing, React Cosmos only supports Creact React App and Nextjs.


Peer Review Contributions by: Odhiambo Paul