How to Build a Blog CMS with React JS?

Websolutionstuff | Nov-13-2023 | Categories : React JS

Are you a blogger who expresses his thoughts with the help of words? If yes, then you might have once thought to create your own blog and have full control over your content and its presentation. So, you can reach out to your audience as you want.

Here, we have something helpful for you. We will help you build a blog content management system (CMS) using the popular and versatile JavaScript library, React JS.

Blogging has become a powerful means of expression and communication, and having a customized CMS can make your blogging experience seamless and tailored to your unique vision.

So, let's roll up our sleeves and begin this exciting adventure in crafting your very own blog CMS:
 

1. Create a React Project

To start, ensure you have Node.js installed. Create a new project by using the React app:

npx create-react-app MY-BLOG

The React program you created will contain node modules, a src folder, a public folder, and a package.json file.
 

2. Work on the src folder and package.json

Our package.json file will contain many dependencies which secure React’s correct work. But we have covered most of this work in the previous steps. Here is how it should be like:

{
  "name": "blog",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
	"react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-router-dom": "^5.2.0",
    "react-scripts": "4.0.1",
	"web-vitals": "^0.2.4",
	“react-query”: “latest”
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
  	"react-app/jest"
	]
  },
  "browserslist": {
    "production": [
      ">0.2%",
  	"not dead",
  	"not op_mini all"
	],
    "development": [
  	"last 1 chrome version",
  	"last 1 firefox version",
  	"last 1 safari version"
      	]
  }
}

 

3. Create the Homepage

Now comes the part of developing the homepage of our blog CMS. We will depend on BlogList component and useFetch hook for this:

import BlogList from './BlogList';
import useFetch from './useFetch';
 
const Home = () => {
	const {data: blogs, isPending, error} = useFetch('http://localhost:8000/blogs');
 
	return (
    	<div className="home">
            {error && <div>{error}</div>}
            {isPending && <div>Loading...</div>}
            <BlogList blogs={blogs} title="All Blogs"/>
        </div>
 	);
}

Now, import the Link as it will help us in linking texts, images, and URLs. We will import the Link with react-router-dom.

import { Link } from 'react-router-dom';
 
const BlogList = ({blogs, title}) => {
 
return (
import { Link } from 'react-router-dom';
 
const BlogList = ({blogs, title}) => {
 
return (
<div className="blog-list">
<h2>{title}</h2>
{blogs.map(blog => (
<div className="blog-preview" key={blog.id}>
<Link to={`/blogs/${blog.id}`}>
<h2>{blog.title}</h2>
<p>Written by {blog.author}</p>
</Link>
</div>
))}
</div>
);
}
 
export default BlogList;

 

4. Make a Component Folder

Next, make a component folder inside src and create two files: 
1.Post 
2.Posts

import React from "react";
import "./Posts.css";
import Post from "../Post/Post";

Next, establish a components directory named "Insider" within the source (src) folder and generate two files within it: "Post" and "Posts". In Posts.jsx, create an arrow function "blog posts". In this function, develop an array of objects named "titles" for the blog post titles. Additionally, within each post's body, include an object for the author's name and the URL of the author's image.

const Posts = () => {
const blogPosts = [
	{
	title: "Websolutionstuff",
body: `Welcome to Websolutionstuff, your ultimate destination for all things digital! We're your go-to experts for website development, mobile app creation, and stunning UI/UX design. What sets us apart is a symphony of cutting-edge technology, boundless creativity, and unwavering commitment. Our team of tech experts transforms your ideas into captivating digital realities, all while ensuring seamless functionality and a user-centric experience. With a track record of excellence and a passion for pushing boundaries, we don't just create solutions; we craft digital experiences that resonate. Choose Websolutionstuff today and embark on a journey to digital brilliance!`,
	author: "ABCD ",
	imgUrl:
		"https://websolutionstuff.com//img-practice/banner/building-blog-cms.png",
	},
	{
	title: "web development service ",
body: `We use our programming skills to create different types of apps, including static, dynamic, and integrated ones, using frameworks like Laravel, Angular, and ASP.NET.`,
	author: "ABCD",
	imgUrl:
		"https://websolutionstuff.com//img-practice/banner/web-development.png",
	},
	{
	title: "Mobile App Development",
body: `Make a loyal customer base through an innovative, user-centric mobile application developed by Websolutionstuff. Being a leading mobile app development company in Ahmedabad, we promise you a robust application with an excellent user experience.`,
	author: "ABCD",
	imgUrl:
		"https://websolutionstuff.com//img-practice/banner/mobile-app-development.png",
	},
	{
	title: "UI UX Development",
body: `We blend user research, wireframing, prototyping, and user testing to create designs that resonate with your audience. Let us transform your ideas into captivating digital journeys that engage, delight, and convert users. Explore the endless possibilities with our UI UX development services and embark on a journey towards digital excellence.`,
	author: "ABCD",
	imgUrl:
		"https://websolutionstuff.com//img-practice/banner/ui-ux-development.png",
	},
];
return (
	<div className="posts-container">
	{blogPosts.map((post, index) => (
		<Post key={index} index={index} post={post} />
	))}
	</div>
);
};
export default Posts;

 

5. Build a Create Component

Once you have created a component folder, you need to develop a Create component to add new blog posts in your CMS. It will use useState hook and useHistory hook.

import { useState } from 'react';
import { useHistory } from 'react-router-dom';
 
const Create = () => {
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const [author, setAuthor] = useState('Shubham');
const [isPending, setIsPending] = useState(false);
const history = useHistory();
 
const handleSubmit = (e) => {
e.preventDefault();
const blog = { title, body, author };
 
setIsPending(true);
 
fetch('http://localhost:8000/blogs', {
method: 'POST',
headers: {"Content-Type": "application/json"},
body: JSON.stringify(blog)
}).then(() => {
setIsPending(false);
history.push('/');
})
}
 
return (
<div className="create">
<h2>Add a New Blog</h2>
<form onSubmit={handleSubmit}>
<label>Blog Title</label>
<input
type="text"
required
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<label>Blog Body:</label>
<textarea
required
value={body}
onChange={(e) => setBody(e.target.value)}
/>
<label>Blog author:</label>
<select
value={author}
onChange={(e) => setAuthor(e.target.value)}
> 
<option value="Shubham">Shubham</option>
<option value="Satyam">Satyam</option>
<option value="Anmol">Anmol</option>
</select>
{!isPending && <button>Add Blog</button>}
{isPending && <button disabled>Adding Blog</button>}
</form>
</div>
);
}
 
export default Create;

 

6. Make Adjustments in useFetch hook

So, we have set up our useFetch hook and now we need to make some adjustments. 

The useState hook will help us in setting three hooks:

  1. data (it will be empty by default)
  2. sPending (set it to true)
  3. error (set it to null)

We will use setTimeout function to delay the fetching process. For the useEffect hook, we will use an abort controller, as well as the timeout function for data fetching using the URL that we received from other components.

import { useState, useEffect } from 'react';
 
const useFetch = (url) => {
	const [data, setData] = useState([]);
	const [isPending, setIsPending] = useState(true);
	const [error, setError] = useState(null);
 
	useEffect(() => {
    	const abortCont = new AbortController();
 
        setTimeout(() => {
            fetch(url, { signal: abortCont.signal })
            .then(res => {
                if(!res.ok)
                {
                    throw Error('Could not fetch data for that resource');
                }
                return res.json();
        	})
            .then((data) => {
                setData(data);
                setIsPending(false);
                setError(null);
        	})
            .catch((err) => {
            	if(err.name==='AbortError') {
                    console.log('Fetch aborted');
                }
                else {
                    setError(err.message);
                    setIsPending(false);
 	           }
        	})
    	}, 5);
 
    	return () => abortCont.abort();
	},[url]);
 
	return {data, isPending, error};
}
 
export default useFetch;

 

7. Set up the leftover components

Now, you need to create some components like:

  • Navbar component
  • NotFound Component
  • App Component
  • Index.css
  • Index.js.

The Navbar component will display the navigation bar in the App.

import { Link } from 'react-router-dom';
 
const Navbar = () => {
return (
<nav className="navbar">
<h1>React Blog App</h1>
<div className="links">
<Link to="/">Home</Link>
<Link to="/create">Create Blog</Link>
</div>
</nav>
);
}
 
export default Navbar;

The NotFound component will display the 404 Error page.

import { Link } from "react-router-dom"
 
 
const NotFound = () => {
return (
<div className="not-found">
<h2>404 Error</h2>
<p>We cannot find that page!</p>
<Link to='/'>Take me back to Home</Link>
</div>
);
}
 
export default NotFound;

The App component will bind and interlink all the components together.

import Navbar from './Navbar';
import Home from './Home';
import Create from './Create';
import BlogDetails from './BlogDetails';
import NotFound from './NotFound';
import { BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import { QueryClient, QueryClientProvider } from 'react-query'
function App() {
const queryClient = new QueryClient()
return (
<QueryClientProvider client={queryClient}>
<Router>
<div className="App">
<Navbar/>
<div className="content">
<Switch>
<Route exact path="/">
<Home/>
</Route>
<Route path="/create">
<Create/>
</Route>
<Route path="/blogs/:id">
<BlogDetails/>
</Route>
<Route path="*">
<NotFound/>
</Route>
</Switch>
</div>
</div>
</Router>
</QueryClientProvider>
);
}
 
export default App;

You will need a CSS file for the design of your app. So, create an attractive file and import it:

import React from "react";
import "./App.css";


import Posts from "./components/Posts/Posts";
const App = () => {
return (
	<div className="main-container">
	<h1 className="main-heading">
		Blog App using React Js
	</h1>
	<Posts />
	</div>
);
};
export default App;

Index.js will be used as an index file and will work as a starting point of our application.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
 
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

 

8. Set up the JSON server

In the final step, we will build a fake Rest API and set up the JSON server.

npm install -g json-server

Now, create a data folder and make a db.json file in it, and use the following command:

{
"blogs": [
{
"title": "1st blog",
"body": "Greetings.",
"author": "Author 1",
"id": 1
},
{
"title": "2nd blog",
"body": "Hello.",
"author": "Author 2",
"id": 2
},
{
"title": "3rd blog",
"body": "Hi",
"author": "Author 3",
"id": 3
}
]
}

Once you are done with setting up the server, start it with this command:

npx json-server — watch data/db.json — port 8000

 

Conclusion

Building your own blog CMS is a rewarding journey that will help you test and grow your creativity as well as your technical skills. Throughout our blog, we've explored the essential components and functionalities needed to develop the blog CMS.

As you continue to refine and expand your CMS, remember that the key to success is your willingness to learn and adapt. Stay up-to-date with the ever-evolving React JS world, leverage the wealth of resources available, and don't be afraid to experiment with new ideas.
 


You might also like:

Recommended Post
Featured Post
How to Create Custom Error Page in Laravel 11
How to Create Custom Error Pag...

Hello developers! In this article, we'll see how to create a custom error page in laravel 11. Here, we'll custom...

Read More

May-08-2024

How To Add jQuery Datatable Column Filter Dropdown On Top
How To Add jQuery Datatable Co...

In this article, we will see how to add a jquery datatable column filter dropdown on top. Here, we will learn how t...

Read More

Jan-19-2023

Datatables Localization Example
Datatables Localization Exampl...

In this post i will show you datatables localization example, jquery datatable plugin can localize a...

Read More

May-10-2021

How To Add Column In Existing Table In Laravel 10
How To Add Column In Existing...

In this article, we will see how to add a column to the existing table in laravel 10 migration. Here, we will learn...

Read More

Apr-24-2023