React Project: HashTags for Posts with Auth — Part #2
Tags: react, layout, gridlayout, router
Published: 2021-03-16 11:51:51

This is Part-2. This blog post will explain how to split ReactJS Components. 
In case if you do not have any idea about the basics of ReactJs and how to start with it, you can refer to [link](https://reactjs.org/tutorial/tutorial.html)

**Quick links for our Part Series:**

PART #1 - [Introduction and Installation of ReactJS (This Post)](https://dev.to/selvaece25/react-project-posts-with-auth-app-part-1-2ibi)
PART #2 - ReactJS split the UI by components Components  (This Post)
PART #3 - [React Query for remote data fetching instead of Redux thunk](https://dev.to/selvaece25/react-project-hashtags-for-posts-with-auth-part-3-10ch)
PART #4 - [Internationalization with i18next](https://dev.to/selvaece25/react-project-hashtags-for-posts-with-auth-part-4-45l2)
PART #5 - Basics to Advanced Usage of styled-components 

Keep in mind that if you get stuck on any step, refer to the [Github repo](https://github.com/selvaece25/react-social-authors-js-app)

To find the completed project, [Demo link] (https://0bkge.csb.app/)

> Components let you split the UI into independent, reusable pieces, and think about each piece in isolation


In React it's important to split the UI by components, so let's check how many components do we need :

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8usem3efshx88dvq14g.png)

As you can see, seven components are standing out:

* Header
* Filter
* NavBar
* Authors
* Posts
* Author Details
* On-Boarding Forms | Details

A question to ask when creating a component:

**What my component should do ?!** 🤔

State management — The component subscribes to the store
Data fetching — It gets the state from the store
UI presentation — It renders 
Business logic — It’s tied to the business logic of the application.

I Will explain one by one component.

#### Header Component
The header component is pretty simple, it contains the project title

```javascript
import React from "react";

const Heading = ({ title }) => {
  return (
    <div className="col">
      <h1>{title}</h1>
    </div>
  );
};

export default Heading;
```

#### Filter Component
The Filter component should:

* Filling input fields with a JSON Array 
* Apply Filter
* Query the API with this filter

In order to save the state of our input, we will use in this component the custom hook.

```javascript
import React from 'react';
import { useDispatch } from 'react-redux';

import useFilterHook from '../../hooks/useFilterHooks';
import { authorsFiltering } from './author-slice';
import { useTranslation } from "react-i18next";


const filterTypes = [
  {
    type: 'Radio',
    default: 'mr',
    selected: 'Mr',
    list: [
      { label: 'All', value: 'All' },
      { label: 'Mr.', value: 'mr' },
      { label: 'Miss.', value: 'miss' },
    ],
    optional: false,
    queryParamKey: 'title',
    placeholder: null,
    title: 'title',
  },
  {
    type: 'Text',
    default: '',
    selected: '',
    list: [],
    optional: false,
    queryParamKey: 'firstName',
    placeholder: 'Search by FirstName',
    title: 'first_name',
  },
  {
    type: 'Text',
    default: '',
    selected: '',
    list: [],
    optional: false,
    queryParamKey: 'lastName',
    placeholder: 'Search by LastName',
    title: 'last_name',
  },
  {
    type: 'Text',
    default: '',
    selected: '',
    list: [],
    optional: false,
    queryParamKey: 'email',
    placeholder: 'Search by Email',
    title: 'Email',
  },
];



const Filter = () => {
  const dispatch = useDispatch();
  const { t: translation  } = useTranslation();

  const filtering = () => {
    dispatch(authorsFiltering({ search_keys: inputs }));
  }

  const {inputs, handleInputChange, handleSubmit} = useFilterHook({ }, filtering);
  return (
    <div>
      <h4> {translation('filters')} </h4>
      <form onSubmit={handleSubmit} autoComplete="off">
      {filterTypes.map((filter) => (
        <article className='card-group-item' key={`${filter.title}`}>
          <header className='card-header'>
            <h6 className='border-bottom border-3'>
              {translation(filter.title)}
            </h6>
          </header>
            <div className='card-body'>
              {filter.type === 'Radio' ? (
                filter.list.map((item) => (
                  <label className='form-check' key={`${item.label}`}>
                    <input
                      type='radio'
                      name={filter.queryParamKey}
                      value={item.value} 
                      onChange={ handleInputChange}
                      
                    />
                    <span className='form-check-label'> {item.label}</span>
                  </label>
                ))
              ) : (
                <input
                  className='form-check-input'
                  type='text'
                  name={filter.queryParamKey}
                  onChange={handleInputChange}
                />
              )}
            </div>
        </article>
      ))}
      <br />
      <button type='submit' className='btn btn-primary left'>
        { translation('apply')}
      </button>
      </form>
    </div>
  );
};

Filter.displayName = 'Filter';
export default Filter;

```
#### Authors Component
The Authors component should:

* get Authors from dummyAPi using react Query
* Loop on this array and render list 

```javascript
import React, { useEffect, lazy } from 'react';
import { useSelector, useDispatch } from 'react-redux';

import { useAuthors } from './authors-hooks';
import { authorSelector, authorsReceived } from './author-slice';

const AuthorListView = lazy(() => import('./author-listing-view'));
const NoResult = lazy(() => import('../../components/empty-list'));
const Loader = lazy(() => import('../../components/loader'));

const AuthorListing = () => {
  
  const { authors, filters: authorFilter } = useSelector(authorSelector);
  const dispatch = useDispatch();

  const { data, isFetching } = useAuthors();
  const renderStatus = data && data.data;

  useEffect(() => {
    if (renderStatus) {
      dispatch(authorsReceived(data.data));
    }
  }, [renderStatus]); // eslint-disable-line react-hooks/exhaustive-deps

  const authorItemList = authors.map((authorDetails) => {
    return (
      <AuthorListView
        key={`${authorDetails.firstName}-${authorDetails.lastName}`}
        user={authorDetails}
      />
    );
  });

  const authorFilterView = Object.keys(authorFilter).map((filter) => {
    return (
      <button class="btn btn-secondary ml-4">{filter.toUpperCase()} <span class="badge">{ authorFilter[filter] } </span></button>
    );
  });

  if (isFetching) {
    return <Loader />;
  }
  return <div>
    <div>{ authorFilterView }</div>
    {authors.length ? authorItemList : <NoResult />}
    </div>;
};

AuthorListing.displayName = 'AuthorsListing';
export default AuthorListing;

```

#### Posts Component
The Posts component should:

* get posts from dummyAPi using react Query
* Loop on this array and render list

```javascript
import React, { lazy } from 'react';
import { usePosts } from './posts-hooks';

const PostListView = lazy(() => import('./post-listing-view'));
const NoResult = lazy(() => import('../../components/empty-list'));
const Loader = lazy(() => import('../../components/loader'));

const PostsListing = () => {
  const { data, isFetching } = usePosts();
  const posts = (data && data.data) || [];

  const postItemList = posts.map((postDetails) => {
    return <PostListView key={`${postDetails.text}`} post={postDetails} />;
  });

  if (isFetching) {
    return <Loader />;
  }
  return <div>{posts.length ? postItemList : <NoResult />}</div>;
};

PostsListing.displayName = 'PostsListing';
export default PostsListing;

```
To be continued [Part-3](https://dev.to/selvaece25/react-project-hashtags-for-posts-with-auth-part-3-10ch)