How to create React Micro Frontend/Microservice (example) cloning NY Times sidebar widget
Tags: microservices, javascript, learning, react
Published: 2022-12-28 12:07:37

Bonjour,
Today, I will try to demonstrate a concept of microservice in react js. We all know that Cloud Microservice Architecture is the favorite architecture of many developers these days. One of the popular examples in production with monthly traffic of 387.17M (Oct, 22) is **"Netflix"**. My example is just a small widget, nothing compared to Netflix of course.

I am going to clone a sidebar widget of **NY times**. 

**Steps 1**
For this just create a new react app using this command

`npx create-react-app ny-times-microservice-widget-clone`

Now, download some packages

`npm i axios`
`npm i parcel`

Then add the following code in the package.json file.

`"build:widget": "parcel build src/index.js --no-source-maps --dist-dir widget",`

Now let's start some coding :)

**Steps 2**

- Create a folder **components** inside the src folder.
- Create a new file inside named _PostsWidget.jsx_ 
- Write the following lines of code.

```
const PostsWidget = () => {
  return (
    <section>
      <div>
        <h3>Tags</h3>
        <h3>This is a title</h3>
        <p>1 Reactions</p>
      </div>
    </section>
  );
};

export default PostsWidget;
```

Here we just created a component that will render two headings and one paragraph at the front-end. Let's add some styling (Note: all styling is copied from NY Times).

- Create a new file inside **components** folder named _PostsWidget.module.css_

```
.storyWrapper{
 border-bottom: 1px solid #dfdfdf;
 padding: 16px 0px
}

.subHeading{
    color: #727272;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    line-height: 1.35em !important;
    letter-spacing: 1px !important;
    margin-bottom: 0.25rem;
}

.mainHeadind{
    color: #121212;
    font-size: 1.375rem;
    line-height: 1.2em;
    letter-spacing: 0.01em;
    font-weight: 700;
    -webkit-font-smoothing: antialiased;
    margin: 0;
}

.reactions{
    color:  #727272;
    font-size: 0.625rem;
    line-height: 1.25em;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin: 0;
    margin-top: 0.25rem;
}
```

```
import styles from "./PostsWidget.module.css";
...
<h3 className={styles.subHeading}>Tags</h3>
<h3 className={styles.mainHeadind}>This is a title</h3>
<p className={styles.reactions}>1 Reactions</p>
...
```

**Steps 3**
API integration, I am using dummyjson.com for dummy data. 

```
const [articles, setArticles] = useState([]);
...
useEffect(() => {
    axios
      .get(`https://dummyjson.com/posts?skip=0&limit=5`)
      .then(function (response) {
        console.log("response", response?.data);
        setArticles(response.data);
      })
      .catch(function (error) {
        setError("error");
      });
  }, [limit, skip]);
...
```

**Step 4**
A div with data attributes to pass props and render this widget. 
`<div class="post-widget" data-skip="0" data-limit="5"></div>`

**Step 5**
Targeting this div and passing props to our component. Go to src/index.js. Now, we'll use a JavaScript selector (querySelectorAll) to target the div. Then we will loop through it so we can render this widget as many times as we want on the same page. 
```
...
import PostsWidget from './components/PostsWidget.jsx';

const widgets = document.querySelectorAll('.post-widget')

widgets.forEach(widget => {
    ReactDOM.render(
        <React.StrictMode>
            <PostsWidget widget={widget} />
        </React.StrictMode>,
        widget
    );
})
...
```
Then, get this prop inside component and passing it to API endpoint.

```
...
const PostsWidget = ({ widget }) => {
  const skip = widget.getAttribute("data-skip") || 0;
  const limit = parseInt(widget.getAttribute("data-limit") ?? 5);
...
  const [error, setError] = useState(false);

  useEffect(() => {
    axios
      .get(`https://dummyjson.com/posts?skip=${skip}&limit=${limit}`)
      .then(function (response) {
        console.log("response", response?.data);
        setArticles(response.data);
      })
      .catch(function (error) {
        setError("error");
      });
  }, [limit, skip]);

  if (error) {
    return <div>{error}</div>;
  }
```

now map all the articles

```
...
{articles?.posts?.map((article) => {
        return (
          <div className={styles.storyWrapper} key={article.id}>
            <h3 className={styles.subHeading}>{article?.tags?.toString()}</h3>
            <h3 className={styles.mainHeadind}>
            {article?.title}
            </h3>
            <p className={styles.reactions}>{article?.reactions} Reactions</p>
          </div>
        );
})}
...
```

**Step 6**
Build, a normal react build will create multiple static files but we need a single file for JavaScript and CSS to target this widget. For this purpose, we install **Parcel** at the start. Let's create a build using this package.

`yarn build:widget`

**Step 7**
Host your widget somewhere. For learning purposes, I've served this build locally and used it inside an HTML file to show you guys.

```
...
<link rel="stylesheet" href="http://192.100.00.00:3000/index.css">
....
<body>
  <div class="post-widget" data-skip="0" data-limit="5"></div>
  <script src="http://192.100.00.00:3000/index.js"></script>
</body>
...
```
You can find the complete code [here](https://github.com/MuhammadAzfarAslam/ny-times-microservice-widget-clone). My vscode directory before the build.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ojpo1n89sginpnnbhzlc.png)

My vscode directory after the build.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nf4amc57jeslse1sktnu.png)

NY times widget for reference

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ggsx1gzvizmrl17ipcfk.png)


This is how _react widget_ will look.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z71kc4uo2x4nzxl3t4a1.png)

**What if we need only the JS link and HTML div, no CSS link**
Yes, we can do it. just need to add another hook. Go to your PostWidget.js file and write following code

```
useEffect(() => {
    const fetchCSS = async () => {
      try {
        const response = await axios.get('http://192.100.00.00:3000/index.css');
        const style = document.createElement('style');
        style.textContent = response.data;
        document.head.appendChild(style);
      } catch (error) {
        console.error(error);
      }
    };
    fetchCSS();
  }, []);
```

This hook will add your CSS code in the head direct. This is one way of doing it, not sure which one is better. Let me know your opinion in the comments.
 

If you find this standalone react app (microservice) helpful then please like ❤ and share it with your friends, follow me on [LinkedIn](https://www.linkedin.com/in/muhammad-azfar-aslam) for more helpful resources.

__________________________________________________________________

## Other links:

- [Highlight on the new features of Next JS 13 config 2022](https://dev.to/muhammadazfaraslam/highlight-on-the-new-features-of-next-js-13-config-2022-1a3i)
- [How to configure React JS app on WSL2 Windows 10](https://dev.to/muhammadazfaraslam/how-to-configure-react-js-app-on-wsl2-windows-10-3d1n)
- [Custom 'Tooltip' component using Tailwind and React Js](https://dev.to/muhammadazfaraslam/custom-tooltip-component-using-tailwind-and-react-js-186g)