Bulding a Twitter What's Happening Bar Form in Reactjs
Tags: react, javascript, webdev, tutorial
Published: 2021-01-13 14:48:05

---
title: Bulding a Twitter What's Happening Bar Form in Reactjs
published: true
description: 
tags: react, javascript, webdev, tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/h6h2wjicsu63hrpbr0z1.png
---

In today post we will use [usetheform](https://github.com/iusehooks/usetheform) + [draftjs](https://draftjs.org/) (Rich Text Editor Framework for React) to build an example of a Twitter what's happening form bar.

### 🎉 Final Result 🎉

{% codesandbox twitter-bar-form-czx3o %}

# Introduction

When we post a new Tweet it basically consists of a collection of information like images, videos, plain text, emoji, ...etc which will be sent to Twitter through a POST api.

If we wanted to build something similar to its what's happening bar, we could think to develop it as a web Form.
 
A web form consists of a collection of HTML field elements grouped within a **\<form\>** tag. HTML supports different field elements, like for instance:

- **\<input />** which defines an HTML form for user input
- **\<textarea />** which defines a multi-line input control (text area)
- **\<select />** which defines a drop-down list

For the complete list of all the HTML form elements supported, please refer to [w3schools form elements](https://www.w3schools.com/html/html_form_elements.asp).

# Setting up the Form Skeleton

In React, we can declaratively reproduce our form skeleton like the following:

```javascript
import React from "react";
import { Form } from "usetheform";
// ...rest of the imports 

const MAX_CHARS_ALLOWED = 50;
export default function App() {
  return (
   <Form onSubmit={(formState) => console.log(formState) }>
     <WhatsHappeningBar maxChars={MAX_CHARS_ALLOWED} />
     <Preview />
     <PrivacyPicker />
     <UploadMediaBar />
     <CharacterCounter maxChars={MAX_CHARS_ALLOWED} />
     <Submit /> 
   </Form>
  );
 }
```

When an user submits the form, the value of **formState** will look like:

```javascript
const formState= {
   editor: { 
     editorState: {}, // the Draftjs editor state
     refEditor: {}, // a DOM ref to the Draftjs editor
     plainText: "abc ...etc"
   },
   postPrivacy: "0", // possible values "0","1","2"
   gif: { }, // present if any gif is uploaded,
   media: [img, video, ..etc] // present if any media is uploaded
}
```

To better understand how the above **formState** is composed we will focus on the components that create and handle the main "pieces" of the **formState**.

# Let's start

The first important "piece" of the **formState** we are going to analyze is the **editor**:

```javascript
const formState= {
   ....,
   editor: { 
     editorState: {}, // the Draftjs editor state
     refEditor: {}, // a DOM ref to the Draftjs editor
     plainText: "abc ...etc"
   }
}
```

which is created and handled by the **\<WhatsHappeningBar />** component.

### ⚛️ **WhatsHappeningBar**
 
```javascript
import React from "react";
import { Collection, Input } from "usetheform";
import { DraftEditor } from "./DraftEditor";
import { extractPlainText } from "./utils/extractPlainText";
import { limitTo } from "./utils/limitTo";

export const WhatsHappeningBar = ({ maxChars }) => {
  return (
    <Collection
      object
      name="editor"
      validators={[limitTo(maxChars)]}
      reducers={extractPlainText}
    >
      <DraftEditor name="editorState" maxChars={maxChars} />
      <Input type="hidden" name="plainText" />
    </Collection>
  );
};
```

An object or an array of "usetheform" library is represented by the **\<Collection />** component, which creates within the form state the **editor** object. 

Collection component contains the validation function which validates the form state based on the text length of the editor and also a reducer function which extracts the "plainText" from the draftjs "editorState". The full code at: [validator](https://codesandbox.io/s/twitter-bar-form-czx3o?file=/src/components/WhatsHappeningBar/utils/limitTo.js:0-181) and [reducer](https://codesandbox.io/s/twitter-bar-form-czx3o?file=/src/components/WhatsHappeningBar/utils/extractPlainText.js)

For more details on how **\<Collection />** works, please refer to the [Collection docs](https://iusehooks.github.io/usetheform/docs-collection).

The second "piece" within the **formState** we will look at is the **postPrivacy**

```javascript
const formState= {
   ....,
   postPrivacy: "0", // possible values "0","1","2"
}
``` 

which is created and handled by the **\<PrivacyPicker />** component.

### ⚛️ **PrivacyPicker**

For sake of simplicity, what is shown below is a basic implementation of the  **\<PrivacyPicker />** component made up be three input radios. Full implementation at: [PrivacyPicker component](https://codesandbox.io/s/twitter-bar-form-czx3o?file=/src/components/PrivacyPicker/PrivacyPicker.jsx:0-2060)

```javascript
import React from "react";
import { Input} from "usetheform";

export const PrivacyPicker = () => {
  return (
   <div className="PrivacySelection__Radios">
     <Input name="postPrivacy" type="radio" value="0" checked />
     <Input name="postPrivacy" type="radio" value="1" />
     <Input name="postPrivacy" type="radio" value="2" />
   </div>
  );
};
```

The **\<Input type="radio" />** component of **"usetheform"** creates a piece of state within a Form named "postPrivacy", which holds the privacy value picked by the user. More details about it at: [Input docs](https://iusehooks.github.io/usetheform/docs-input).

Another component worthy to be mentioned is the **\<UploadGif />** 
which creates and handles the following "piece" of **formState**:

```javascript
const formState= {
   ....,
   gif: { ...gifProps }
}
``` 

### ⚛️ **UploadGif**

```javascript
import React, { useEffect, useState } from "react";
import { useField } from "usetheform";
 
export const UploadGif = () => {
  const { setValue } = useField({ type: "custom", name: "gif" });
  const [showGrid, toggleGrid] = useState(() => false);
  const toggleGifGrid = () => toggleGrid((prev) => !prev);
  const onGifClick = (gif, e) => {
    e.preventDefault();
    setValue(gif);
    toggleGifGrid();
  };
  return (
    <div>
      <button type="button" onClick={toggleGifGrid}>
        <img alt="Upload GIF" src={UpladGifSVG} />
      </button>
      {showGrid && (
        <GifGrid onCloseGifGrid={toggleGifGrid} onGifClick={onGifClick} />
      )}
    </div>
  );
};
``` 

The **useField** hook allows to build a custom input primitives.
When a user picks any gif image a callback function will be invoked **<GifGrid onGifClick />** and the gif object will be pushed into the formState:

```javascript
  const onGifClick = (gif, e) => {
    e.preventDefault();
    setValue(gif); // pushing into the formState
    toggleGifGrid();
  };
```

More details about useField at: [useField doc](https://iusehooks.github.io/usetheform/docs-use-field)

The last, but not least, component we will look at is the **\<CharacterCounter/>** component.

### ⚛️ **CharacterCounter**

```javascript
import React from "react";
import { useSelector } from "usetheform";
import { ProgressRingBar } from "./../ProgressRingBar/ProgressRingBar";
import { getProgressRingBarProps } from "./utils/getProgressRingBarProps";
 
export const CharacterCounter = ({ maxChars }) => {
  const [plainText] = useSelector((state) => state.editor.plainText);

  const props = getProgressRingBarProps(plainText, maxChars);

  return (
    <ProgressRingBar {...props}  />
  );
};
```

The **CharacterCounter** component counts the typed characters. In order to do so it uses the **useSelector** hook for picking the **plainText** from the form state using the utils function named **getProgressRingBarProps** . 

More details about useSelector at: [useSelector doc](https://iusehooks.github.io/usetheform/docs-use-selector)

# Conclusion

Hope you enjoyed reading this post. If you did so, please, use the buttons below to share it. 🙏 Thanks for reading!

<a href="https://twitter.com/intent/tweet?text=Bulding%20a%20Twitter%20What's%20Happening%20Bar%20Form%20in%20Reactjs&url=https://dev.to/antonio_pangall/bulding-a-twitter-what-s-happening-bar-form-in-reactjs-27d&hashtags=ReactJS,webdev,javascript,DEVCommunity,usetheform"><img src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social" alt="Tweet" height="20" /></a>

<a href="https://www.linkedin.com/sharing/share-offsite/?url=https://dev.to/antonio_pangall/bulding-a-twitter-what-s-happening-bar-form-in-reactjs-27d&title=Bulding%20a%20Twitter%20What's%20Happening%20Bar%20Form%20in%20Reactjs&source=dev.to"><img src="https://img.shields.io/badge/LinkedIn-blue?style=flat&logo=linkedin&labelColor=blue" alt="Linkedin" height="20" /></a>