ZEMOSO ENGINEERING STUDIO
July 8, 2021
5 min read

Product engineering zeitgeist: Implement OOPs in React JS using atomic design

Atomic design and object-oriented programming is the zeitgeist for today’s developers. But what and how can it be applied successfully for building products that are growing fast.

In another article about atomic design, we’ve discussed how to apply the fundamental principles and categorize components into atoms, molecules, or organisms. In this article, we dive deeper on how to implement this principle, design, and write code for these components. 

Software development lifecycle process (SDLC)

One common oversight by most developers is to start building a solution before fully understanding the requirements and functionalities. The result is many iterations, work-arounds, and bug fixes that are effort intensive at a later stage and take away from the quality of the code. 

Even when dealing with ambiguity, one must take the time to understand what provisions to build into the coding and engineering for ease of enhancements and iterations in the future. 

Development Process

For example, in a reminder app, we can build one atom and one organism. 

1. TextField atom

2. AddEvent organism

TextField

Design the component structure

1. Decide whether to make it a stateful component or stateless component. The TextField is just supposed to take the input. Validations, errors, state management, etc. will be handled by the parent. Therefore, we’ll go with stateless.

2. Convert the requirements to props.

In the above code, there are a couple of extra props than earlier planned. This is fairly common. While it might be possible to think of all the scenarios all at once, it is good to have provisions for most of them. 

There are no props for styling, because all the styling is handled by the theme, and will prevent other developers from overriding the uniform aesthetics of the application. 

We always define the props first. This lays the path for the rest of the development. It also allows other developers, dependent on this component, to plan their development with ease, accelerating product development overall. 

Implement the final code.

We can destructure the props easily, in accordance with our clients’ standards. 

AddEvent

AddEvent organism is going to be a stateful component. This is our process for ensuring on-time delivery of the product. 

Identify the props

This is going to be more complex than what we did for a stateless component. 

First thing to decide is if the component is going to be the owner of this functionality or will it be controlled by its parent.
Next, answer this question: what is the impact of this component on the rest of the application?


Finally, identify how this component is going to be reused across the application. 

Design

We like to think of this component as a closed container, where it internally handles most of the processes. Few of its responsibilities are: 

1. Render the correct UI

2. Handle the user input

3. Collate these data

4. Optional — Once the user clicks submit, then send the processed data back to the parent

In these scenarios, though the responsibility is high, most of it is abstracted and need not be exposed as props. 

Implementation

import React, { useCallback, useState } from "react";

import PropTypes from "prop-types";


import { makeStyles } from "@material-ui/core/styles";

import Container from "@material-ui/core/Container";

import Box from "@material-ui/core/Box";

import Grid from "@material-ui/core/Grid";


import Typography from "components/atoms/Typography";

import TextField from "components/atoms/TextField";

import Button from "components/atoms/Button";


const useStyle = makeStyles((theme) => ({}));


const AddEventBanner = (props) => {

 const validate = { props };

 const style = useStyle();


 const [fieldToValidate, setFieldValidation] = useState({

   title: false,

   date: false,

   type: false,

 });


 const [inputFieldValue, setFieldValue] = useState({

   title: "",

   description: "",

   date: "",

   type: "",

 });


 const validateField = useCallback(

   (field) => {

     const input = inputFieldValue[field];

     const currentValidationState = fieldToValidate;

     if (input === null || input === "") {

       currentValidationState[field] = true;

     } else {

       currentValidationState[field] = false;

     }

     setFieldValidation({ ...currentValidationState });

     return !currentValidationState[field];

   },

   [inputFieldValue, fieldToValidate, setFieldValidation]

 );


 const isValid = useCallback(() => {

   let validationStatus = true;

   Object.keys(fieldToValidate).map((key, value) => {

     validationStatus = validationStatus && validateField(key);

     console.log(validationStatus);

   });

   return validationStatus;

 }, [fieldToValidate, validateField]);


 const handleFieldChange = useCallback(

   (field, value) => {

     const currentValidationState = fieldToValidate;

     currentValidationState[field] = false;

     setFieldValidation({ ...currentValidationState });


     const currentFieldValues = inputFieldValue;

     currentFieldValues[field] = value;

     setFieldValue({ ...currentFieldValues });

   },

   [fieldToValidate, inputFieldValue, setFieldValidation, setFieldValue]

 );


 const handleSubmit = useCallback(() => {

   if (!props.validate || (props.validate && isValid())) {

     props.onSubmit(inputFieldValue);

   }

 }, [isValid]);


 return (

   <Box component={Container}>

     <Grid container spacing={2}>

       <Grid item>

         <Typography variant="header">Add New Event</Typography>

       </Grid>

       <Grid item xs={12}>

         <TextField

           required

           label="Title"

           onChange={(event) => handleFieldChange("title", event.target.value)}

           error={fieldToValidate.title}

           onBlur={() => validate && validateField("title")}

         />

       </Grid>

       <Grid item xs={12}>

         <TextField

           label="Description"

           onChange={(event) =>

             handleFieldChange("description", event.target.value)

           }

         />

       </Grid>

       <Grid item xs={6}>

         <TextField

           required

           label="Date and Time"

           onChange={(event) => handleFieldChange("date", event.target.value)}

           type="datetime-local"

           error={fieldToValidate.date}

           onBlur={() => validate && validateField("date")}

         />

       </Grid>

       <Grid item xs={6}>

         <TextField

           required

           label="Event Type"

           onChange={(event) => handleFieldChange("type", event.target.value)}

           error={fieldToValidate.type}

           onBlur={() => validate && validateField("type")}

         />

       </Grid>

       <Grid item container xs={12} justify="center">

         <Button title="Add Event" onClick={handleSubmit} />

       </Grid>

     </Grid>

   </Box>

 );

};


AddEventBanner.propTypes = {

 validate: PropTypes.bool,

 onSubmit: PropTypes.func,

};


AddEventBanner.defaultProps = {

 validate: false,

};


export default AddEventBanner;


AddEvent.js hosted with ❤ by GitHub. View raw code here

You can take a peek at my reference code for this post and project here

An earlier version of this blog was published on Medium by the author. 

ZEMOSO ENGINEERING STUDIO

Product engineering zeitgeist: Implement OOPs in React JS using atomic design

By Zemoso Engineering Studio
July 8, 2021
5 min read

Atomic design and object-oriented programming is the zeitgeist for today’s developers. But what and how can it be applied successfully for building products that are growing fast.

In another article about atomic design, we’ve discussed how to apply the fundamental principles and categorize components into atoms, molecules, or organisms. In this article, we dive deeper on how to implement this principle, design, and write code for these components. 

Software development lifecycle process (SDLC)

One common oversight by most developers is to start building a solution before fully understanding the requirements and functionalities. The result is many iterations, work-arounds, and bug fixes that are effort intensive at a later stage and take away from the quality of the code. 

Even when dealing with ambiguity, one must take the time to understand what provisions to build into the coding and engineering for ease of enhancements and iterations in the future. 

Development Process

For example, in a reminder app, we can build one atom and one organism. 

1. TextField atom

2. AddEvent organism

TextField

Design the component structure

1. Decide whether to make it a stateful component or stateless component. The TextField is just supposed to take the input. Validations, errors, state management, etc. will be handled by the parent. Therefore, we’ll go with stateless.

2. Convert the requirements to props.

In the above code, there are a couple of extra props than earlier planned. This is fairly common. While it might be possible to think of all the scenarios all at once, it is good to have provisions for most of them. 

There are no props for styling, because all the styling is handled by the theme, and will prevent other developers from overriding the uniform aesthetics of the application. 

We always define the props first. This lays the path for the rest of the development. It also allows other developers, dependent on this component, to plan their development with ease, accelerating product development overall. 

Implement the final code.

We can destructure the props easily, in accordance with our clients’ standards. 

AddEvent

AddEvent organism is going to be a stateful component. This is our process for ensuring on-time delivery of the product. 

Identify the props

This is going to be more complex than what we did for a stateless component. 

First thing to decide is if the component is going to be the owner of this functionality or will it be controlled by its parent.
Next, answer this question: what is the impact of this component on the rest of the application?


Finally, identify how this component is going to be reused across the application. 

Design

We like to think of this component as a closed container, where it internally handles most of the processes. Few of its responsibilities are: 

1. Render the correct UI

2. Handle the user input

3. Collate these data

4. Optional — Once the user clicks submit, then send the processed data back to the parent

In these scenarios, though the responsibility is high, most of it is abstracted and need not be exposed as props. 

Implementation

import React, { useCallback, useState } from "react";

import PropTypes from "prop-types";


import { makeStyles } from "@material-ui/core/styles";

import Container from "@material-ui/core/Container";

import Box from "@material-ui/core/Box";

import Grid from "@material-ui/core/Grid";


import Typography from "components/atoms/Typography";

import TextField from "components/atoms/TextField";

import Button from "components/atoms/Button";


const useStyle = makeStyles((theme) => ({}));


const AddEventBanner = (props) => {

 const validate = { props };

 const style = useStyle();


 const [fieldToValidate, setFieldValidation] = useState({

   title: false,

   date: false,

   type: false,

 });


 const [inputFieldValue, setFieldValue] = useState({

   title: "",

   description: "",

   date: "",

   type: "",

 });


 const validateField = useCallback(

   (field) => {

     const input = inputFieldValue[field];

     const currentValidationState = fieldToValidate;

     if (input === null || input === "") {

       currentValidationState[field] = true;

     } else {

       currentValidationState[field] = false;

     }

     setFieldValidation({ ...currentValidationState });

     return !currentValidationState[field];

   },

   [inputFieldValue, fieldToValidate, setFieldValidation]

 );


 const isValid = useCallback(() => {

   let validationStatus = true;

   Object.keys(fieldToValidate).map((key, value) => {

     validationStatus = validationStatus && validateField(key);

     console.log(validationStatus);

   });

   return validationStatus;

 }, [fieldToValidate, validateField]);


 const handleFieldChange = useCallback(

   (field, value) => {

     const currentValidationState = fieldToValidate;

     currentValidationState[field] = false;

     setFieldValidation({ ...currentValidationState });


     const currentFieldValues = inputFieldValue;

     currentFieldValues[field] = value;

     setFieldValue({ ...currentFieldValues });

   },

   [fieldToValidate, inputFieldValue, setFieldValidation, setFieldValue]

 );


 const handleSubmit = useCallback(() => {

   if (!props.validate || (props.validate && isValid())) {

     props.onSubmit(inputFieldValue);

   }

 }, [isValid]);


 return (

   <Box component={Container}>

     <Grid container spacing={2}>

       <Grid item>

         <Typography variant="header">Add New Event</Typography>

       </Grid>

       <Grid item xs={12}>

         <TextField

           required

           label="Title"

           onChange={(event) => handleFieldChange("title", event.target.value)}

           error={fieldToValidate.title}

           onBlur={() => validate && validateField("title")}

         />

       </Grid>

       <Grid item xs={12}>

         <TextField

           label="Description"

           onChange={(event) =>

             handleFieldChange("description", event.target.value)

           }

         />

       </Grid>

       <Grid item xs={6}>

         <TextField

           required

           label="Date and Time"

           onChange={(event) => handleFieldChange("date", event.target.value)}

           type="datetime-local"

           error={fieldToValidate.date}

           onBlur={() => validate && validateField("date")}

         />

       </Grid>

       <Grid item xs={6}>

         <TextField

           required

           label="Event Type"

           onChange={(event) => handleFieldChange("type", event.target.value)}

           error={fieldToValidate.type}

           onBlur={() => validate && validateField("type")}

         />

       </Grid>

       <Grid item container xs={12} justify="center">

         <Button title="Add Event" onClick={handleSubmit} />

       </Grid>

     </Grid>

   </Box>

 );

};


AddEventBanner.propTypes = {

 validate: PropTypes.bool,

 onSubmit: PropTypes.func,

};


AddEventBanner.defaultProps = {

 validate: false,

};


export default AddEventBanner;


AddEvent.js hosted with ❤ by GitHub. View raw code here

You can take a peek at my reference code for this post and project here

An earlier version of this blog was published on Medium by the author. 

Recent Publications
Actual access control without getting in the way of actual work: 2023
Actual access control without getting in the way of actual work: 2023
March 13, 2023
Breaking the time barrier: Test Automation and its impact on product launch cycles
Breaking the time barrier: Test Automation and its impact on product launch cycles
January 20, 2023
Product innovation for today and the future! It’s outcome-first, timeboxed, and accountable
Product innovation for today and the future! It’s outcome-first, timeboxed, and accountable
January 9, 2023
From "great potential" purgatory to "actual usage" reality: getting SDKs right in a product-led world
From "great potential" purgatory to "actual usage" reality: getting SDKs right in a product-led world
December 6, 2022
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 2
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 2
October 13, 2022
Testing what doesn’t exist with a Wizard of Oz twist
Testing what doesn’t exist with a Wizard of Oz twist
October 12, 2022
Docs, Guides, Resources: Getting developer microsites right in a product-led world
Docs, Guides, Resources: Getting developer microsites right in a product-led world
September 20, 2022
Beyond methodologies: Five engineering do's for an agile product build
Beyond methodologies: Five engineering do's for an agile product build
September 5, 2022
Actual access control without getting in the way of actual work: 2023
Actual access control without getting in the way of actual work: 2023
March 13, 2023
Breaking the time barrier: Test Automation and its impact on product launch cycles
Breaking the time barrier: Test Automation and its impact on product launch cycles
January 20, 2023
Product innovation for today and the future! It’s outcome-first, timeboxed, and accountable
Product innovation for today and the future! It’s outcome-first, timeboxed, and accountable
January 9, 2023
From "great potential" purgatory to "actual usage" reality: getting SDKs right in a product-led world
From "great potential" purgatory to "actual usage" reality: getting SDKs right in a product-led world
December 6, 2022
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 2
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 2
October 13, 2022
ZEMOSO ENGINEERING STUDIO
July 8, 2021
5 min read

Product engineering zeitgeist: Implement OOPs in React JS using atomic design

Atomic design and object-oriented programming is the zeitgeist for today’s developers. But what and how can it be applied successfully for building products that are growing fast.

In another article about atomic design, we’ve discussed how to apply the fundamental principles and categorize components into atoms, molecules, or organisms. In this article, we dive deeper on how to implement this principle, design, and write code for these components. 

Software development lifecycle process (SDLC)

One common oversight by most developers is to start building a solution before fully understanding the requirements and functionalities. The result is many iterations, work-arounds, and bug fixes that are effort intensive at a later stage and take away from the quality of the code. 

Even when dealing with ambiguity, one must take the time to understand what provisions to build into the coding and engineering for ease of enhancements and iterations in the future. 

Development Process

For example, in a reminder app, we can build one atom and one organism. 

1. TextField atom

2. AddEvent organism

TextField

Design the component structure

1. Decide whether to make it a stateful component or stateless component. The TextField is just supposed to take the input. Validations, errors, state management, etc. will be handled by the parent. Therefore, we’ll go with stateless.

2. Convert the requirements to props.

In the above code, there are a couple of extra props than earlier planned. This is fairly common. While it might be possible to think of all the scenarios all at once, it is good to have provisions for most of them. 

There are no props for styling, because all the styling is handled by the theme, and will prevent other developers from overriding the uniform aesthetics of the application. 

We always define the props first. This lays the path for the rest of the development. It also allows other developers, dependent on this component, to plan their development with ease, accelerating product development overall. 

Implement the final code.

We can destructure the props easily, in accordance with our clients’ standards. 

AddEvent

AddEvent organism is going to be a stateful component. This is our process for ensuring on-time delivery of the product. 

Identify the props

This is going to be more complex than what we did for a stateless component. 

First thing to decide is if the component is going to be the owner of this functionality or will it be controlled by its parent.
Next, answer this question: what is the impact of this component on the rest of the application?


Finally, identify how this component is going to be reused across the application. 

Design

We like to think of this component as a closed container, where it internally handles most of the processes. Few of its responsibilities are: 

1. Render the correct UI

2. Handle the user input

3. Collate these data

4. Optional — Once the user clicks submit, then send the processed data back to the parent

In these scenarios, though the responsibility is high, most of it is abstracted and need not be exposed as props. 

Implementation

import React, { useCallback, useState } from "react";

import PropTypes from "prop-types";


import { makeStyles } from "@material-ui/core/styles";

import Container from "@material-ui/core/Container";

import Box from "@material-ui/core/Box";

import Grid from "@material-ui/core/Grid";


import Typography from "components/atoms/Typography";

import TextField from "components/atoms/TextField";

import Button from "components/atoms/Button";


const useStyle = makeStyles((theme) => ({}));


const AddEventBanner = (props) => {

 const validate = { props };

 const style = useStyle();


 const [fieldToValidate, setFieldValidation] = useState({

   title: false,

   date: false,

   type: false,

 });


 const [inputFieldValue, setFieldValue] = useState({

   title: "",

   description: "",

   date: "",

   type: "",

 });


 const validateField = useCallback(

   (field) => {

     const input = inputFieldValue[field];

     const currentValidationState = fieldToValidate;

     if (input === null || input === "") {

       currentValidationState[field] = true;

     } else {

       currentValidationState[field] = false;

     }

     setFieldValidation({ ...currentValidationState });

     return !currentValidationState[field];

   },

   [inputFieldValue, fieldToValidate, setFieldValidation]

 );


 const isValid = useCallback(() => {

   let validationStatus = true;

   Object.keys(fieldToValidate).map((key, value) => {

     validationStatus = validationStatus && validateField(key);

     console.log(validationStatus);

   });

   return validationStatus;

 }, [fieldToValidate, validateField]);


 const handleFieldChange = useCallback(

   (field, value) => {

     const currentValidationState = fieldToValidate;

     currentValidationState[field] = false;

     setFieldValidation({ ...currentValidationState });


     const currentFieldValues = inputFieldValue;

     currentFieldValues[field] = value;

     setFieldValue({ ...currentFieldValues });

   },

   [fieldToValidate, inputFieldValue, setFieldValidation, setFieldValue]

 );


 const handleSubmit = useCallback(() => {

   if (!props.validate || (props.validate && isValid())) {

     props.onSubmit(inputFieldValue);

   }

 }, [isValid]);


 return (

   <Box component={Container}>

     <Grid container spacing={2}>

       <Grid item>

         <Typography variant="header">Add New Event</Typography>

       </Grid>

       <Grid item xs={12}>

         <TextField

           required

           label="Title"

           onChange={(event) => handleFieldChange("title", event.target.value)}

           error={fieldToValidate.title}

           onBlur={() => validate && validateField("title")}

         />

       </Grid>

       <Grid item xs={12}>

         <TextField

           label="Description"

           onChange={(event) =>

             handleFieldChange("description", event.target.value)

           }

         />

       </Grid>

       <Grid item xs={6}>

         <TextField

           required

           label="Date and Time"

           onChange={(event) => handleFieldChange("date", event.target.value)}

           type="datetime-local"

           error={fieldToValidate.date}

           onBlur={() => validate && validateField("date")}

         />

       </Grid>

       <Grid item xs={6}>

         <TextField

           required

           label="Event Type"

           onChange={(event) => handleFieldChange("type", event.target.value)}

           error={fieldToValidate.type}

           onBlur={() => validate && validateField("type")}

         />

       </Grid>

       <Grid item container xs={12} justify="center">

         <Button title="Add Event" onClick={handleSubmit} />

       </Grid>

     </Grid>

   </Box>

 );

};


AddEventBanner.propTypes = {

 validate: PropTypes.bool,

 onSubmit: PropTypes.func,

};


AddEventBanner.defaultProps = {

 validate: false,

};


export default AddEventBanner;


AddEvent.js hosted with ❤ by GitHub. View raw code here

You can take a peek at my reference code for this post and project here

An earlier version of this blog was published on Medium by the author. 

Recent Publications

ZEMOSO ENGINEERING STUDIO

Testing what doesn’t exist with a Wizard of Oz twist

October 12, 2022
7 min read
ZEMOSO ENGINEERING STUDIO

Beyond methodologies: Five engineering do's for an agile product build

September 5, 2022
6 min read
ZEMOSO ENGINEERING STUDIO

How we built a big data platform for a futuristic AgriTech product

June 3, 2022
8 min read
ZEMOSO NEWS

Zemoso Labs starts operations in Waterloo, Canada

May 25, 2022
5 min read
ZEMOSO ENGINEERING STUDIO

Honorable mention at O’Reilly’s Architectural Katas event

May 17, 2021
5 min read
ZEMOSO ENGINEERING STUDIO

Product dev with testable spring boot applications, from day one

May 4, 2021
5 min read
ZEMOSO ENGINEERING STUDIO

When not to @Autowire in Spring or Spring Boot applications

May 1, 2021
5 min read
ZEMOSO ENGINEERING STUDIO

Efficiently handle data and integrations in Spring Boot

January 24, 2021
5 min read
ZEMOSO ENGINEERING STUDIO

Our favorite CI/CD DevOps Practice: Simplify with GitHub Actions

October 25, 2020
5 min read
ZEMOSO ENGINEERING STUDIO

How to use BERT and DNN to build smarter NLP algorithms for products

February 14, 2020
12 min read
ZEMOSO ENGINEERING STUDIO

GraphQL — Why is it essential for agile product development?

April 30, 2019
12 min read
ZEMOSO ENGINEERING STUDIO

GraphQL with Java Spring Boot and Apollo Angular for Agile platforms

April 30, 2019
9 min read
ZEMOSO ENGINEERING STUDIO

Deploying Airflow on Kubernetes 

November 30, 2018
2 min read
ZEMOSO PRODUCT STUDIO

How to validate your Innovation: Mastering Experiment Design

November 22, 2018
8 min read
ZEMOSO PRODUCT STUDIO

Working Backwards: Amazon's Culture of Innovation: My notes

November 19, 2018
8 min read
ZEMOSO ENGINEERING STUDIO

Product developer POV: Caveats when building with Spark

November 5, 2018
2 min read

Want more best practices?

Access thought-leadership and best practice content across
the product development lifecycle

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

© 2023  Zemoso Technologies
Privacy Policy

Terms of Use
LinkedIn Page - Zemoso TechnologiesFacebook Page - Zemoso TechnologiesTwitter Account - Zemoso Technologies

© 2021 Zemoso Technologies
Privacy Policy

LinkedIn Page - Zemoso TechnologiesFacebook Page - Zemoso TechnologiesTwitter Account - Zemoso Technologies
May 25, 2023