ZEMOSO ENGINEERING STUDIO
June 5, 2022
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
How to remix Amazon’s Working Backwards with Google’s Venture’s User Journey: The Dr. Strange Way
How to remix Amazon’s Working Backwards with Google’s Venture’s User Journey: The Dr. Strange Way
June 14, 2022
How we built a big data platform for a futuristic AgriTech product
How we built a big data platform for a futuristic AgriTech product
June 3, 2022
Zemoso Labs starts operations in Waterloo, Canada
Zemoso Labs starts operations in Waterloo, Canada
May 25, 2022
Deconstructing Elon Musk’s dog ate my homework answer for Twitter: More validation will be asked of startups
Deconstructing Elon Musk’s dog ate my homework answer for Twitter: More validation will be asked of startups
May 20, 2022
Real Talk: Lessons learned and evolved from 3M and Post-it®’s adoption of Crazy 8 methodology
Real Talk: Lessons learned and evolved from 3M and Post-it®’s adoption of Crazy 8 methodology
April 10, 2022
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 1
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 1
February 7, 2022
Understanding dynamic multi-column search with JPA Criteria for product development
Understanding dynamic multi-column search with JPA Criteria for product development
January 2, 2022
Honorable mention at O’Reilly’s Architectural Katas event
Honorable mention at O’Reilly’s Architectural Katas event
May 17, 2021
Product dev with testable spring boot applications, from day one
Product dev with testable spring boot applications, from day one
May 4, 2021
When not to @Autowire in Spring or Spring Boot applications
When not to @Autowire in Spring or Spring Boot applications
May 1, 2021
Efficiently handle data and integrations in Spring Boot
Efficiently handle data and integrations in Spring Boot
January 24, 2021
Unlock the power of atomic design in React and React Native using a theming library — Part 1
Unlock the power of atomic design in React and React Native using a theming library — Part 1
November 2, 2020
Our favorite CI/CD DevOps Practice: Simplify with GitHub Actions
Our favorite CI/CD DevOps Practice: Simplify with GitHub Actions
October 25, 2020
Kubernetes — What is it, what problems does it solve, and how does it compare with alternatives?
Kubernetes — What is it, what problems does it solve, and how does it compare with alternatives?
June 21, 2019
GraphQL — Why is it essential for agile product development?
GraphQL — Why is it essential for agile product development?
April 30, 2019
Orchestrating backend services for product development with AWS Step Functions
Orchestrating backend services for product development with AWS Step Functions
April 1, 2019
How To Decide When to Use Amazon Working Backwards, Business Model Canvas and Lean Canvas
How To Decide When to Use Amazon Working Backwards, Business Model Canvas and Lean Canvas
November 30, 2018
How to validate your Innovation: Mastering Experiment Design
How to validate your Innovation: Mastering Experiment Design
November 22, 2018
Working Backwards: Amazon's Culture of Innovation: My notes
Working Backwards: Amazon's Culture of Innovation: My notes
November 19, 2018
Product developer POV: Caveats when building with Spark
Product developer POV: Caveats when building with Spark
November 5, 2018
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

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

GraphQL — Why is it essential for agile product development?

April 30, 2019
12 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.

© 2021 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
June 5, 2022