DEV Community

Cover image for How to make a simple post and reply system with React, Firebase, Redux
DenSpec
DenSpec

Posted on • Edited on

How to make a simple post and reply system with React, Firebase, Redux

TRIO

Hi ! Today we meet to see how to make a simple post and reply system with React, Firebase, Redux

Want to see how he behaves?

  • Create post
  • Read post
  • Click on the post which redirects to a link, displaying the post and its responses.
  • Write responses to this post

Here is the structure of the files:

src 
  └──app
     └── components 
        ├── CreatePost.js
        ├── ListPost
        ├── ShowPost.js
        ├── InPost.js
        ├── Reply.js
  └──store
     ├── store.js
     ├── PostSlice.js

   ├── app(router).js

Enter fullscreen mode Exit fullscreen mode

Are you ready ? 👉

Packages

First, you will need to install all the necessary packages.

🤘 Redux 
    "@reduxjs/toolkit": "^1.6.2"
    "react-redux": "^7.2.6"

🔥 Firebase
    "firebase": "^9.5.0"
    "react-firebase-hooks": "^4.0.1"

⬅⬇➡ Router 
"react-router": "^5.2.1"
"react-router-dom": "^5.3.0"
Enter fullscreen mode Exit fullscreen mode

If you haven't set up your router yet, it should look like this:

Router.js
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";

<Router>
         <Switch>
          <Route exact path="/blabla" component={blabla} />
        </Switch>
        </div>
</Router>

Enter fullscreen mode Exit fullscreen mode

➕ Create a post

Now, we will create a file which will be called CreatePost.js
We are going to create a new function which will be called sendPost. Whit Firestore, we will create a new document in the post collection.
In it, we will put different fields including title and message, which will be the value of the inputs and the others the user's information.

    const  inputTitle = useRef(""); 
    const inputMessage = useRef("");

    const db = firebase.firestore();
    const sendPost = useCallback(async event => {
        event.preventDefault();
        if (inputTitle.current.value !== "") {
            db.collection("post").add({
              timestamp: firebase.firestore.FieldValue.serverTimestamp(),
              title: inputTitle.current.value,
              message: inputMessage.current.value,
              name: user.displayName,
              photoURL: user.photoURL,
            }); 
        }
    })

    return (
/* the onSubmit will execute the "sendPost" function. */    
   <form onSubmit="sendPost">
    <input
    ref={inputTitle}
    placeholder="Title"
    >
    <input
    ref={inputMessage}
    placeholder="Message"
    >
    <button type="submit">
    </form>
    )
Enter fullscreen mode Exit fullscreen mode

When you go to Firestore console.firebase.google.com, it would look like this:

Image description

📖 Read a post

Now, we will move on to the second step: 📚 Display the posts.

To do this, start by creating a file named ListPost.

With the useCollection function, we can choose any collection. For this case, we're going to use the 'post' collection. Then, we will make a docs.map, where we will put all the fields.

To be able to read the messages, we will create a file named 'ShowPost', we will display the messages inside.

import { useCollection } from "react-firebase-hooks/firestore"
import ShowPost from './ShowPost.js'
    const db = firebase.firestore();
    const [postlist] = useCollection(
      db
      .collection("post")
      );  

return( 

/* Don't forget to keep the key and the id, it will be important for the future. */

       {postlist?.docs.map((doc) => (

  <MessageShow
  key={doc.id}
  id={doc.id}
  title={doc.data().title}
  name={doc.data().name}
  photoURL={doc.data().photoURL}
  />
))}

)
Enter fullscreen mode Exit fullscreen mode
ShowPost.js

We will import everything we put in the MessageShow, then we just have to use {blabla} so that the text of the field is displayed.

function ShowPost({id, title, name, photoURL}) {

return (
<img src={photoURL}>
<p> {title} </p>
<p> {name} </p>
)
Enter fullscreen mode Exit fullscreen mode

🚗 Redux joined the chat

Create a new Store folder. In it, you will create a file named 'Store.js'. We will inserted given a small-code

/* We import the configureStore from redux */
import { configureStore } from "@reduxjs/toolkit";
import postSlice from "./PostSlice";
export const store = configureStore({
  reducer: {
    post: postSlice,
  },
});
Enter fullscreen mode Exit fullscreen mode

Then you create a new file 'PostSlice.js'


import { createSlice } from "@reduxjs/toolkit";

/* We define the initial state */
const initialState = {
  postId: null,
};

export const postSlice = createSlice({
  name: "post",
  initialState,
  reducers: {
    setPost: (state, action) => {
      state.postId = action.payload.postId;
      state.postName = action.payload.postName;
    },
  },
});

export const { setPostInfo } = postSlice.actions;

export const selectPostId = (state) => state.post.postId;
export const selectPostName = (state) => state.post.postName;

export default postSlice.reducer;


Enter fullscreen mode Exit fullscreen mode

We modify our ' index.js '

/* We import our redux tools */

import { Provider } from "react-redux"
import { store } from "./store/Store"

/* We add a provider */

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
    <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

Enter fullscreen mode Exit fullscreen mode

Now, we come back to our MessageShow.js file


 function ShowPost({id, title, name, photoURL}) {
 const setPost = () => {
        dispatch(
          setPostInfo({
            postId: id,
          })
        );

        history.push(`/post/{$id}`);
      };
return (

/* We now add a div, and when we click on it, it executes the 'setPost' function
We also define the cursor as a pointer
*/

<div onClick={setPost} style={{cursor: 'pointer'}}>
<img src={photoURL}>
<p> {title} </p>
<p> {name} </p>
</div>
)

Enter fullscreen mode Exit fullscreen mode

We now come back to our app (router.js)

/* You just add these two little lines.
Thanks to what we have not added in index.js, we can freely put the id in the router. When it is on the url /post /id/, it will display the component 'InPost.js'
*/

import InPost from './InPost.js'
return ( 
          <Route exact path="/post/message/:id" component={InPost} />
)
Enter fullscreen mode Exit fullscreen mode

📜 InPost

Create a new file named InPost.js

/* We import all the features */

import { useCollection } from "react-firebase-hooks/firestore"
import { selectPostId } from  './store'
import { useSelector } from "react-redux";

fonction InPost(){
    const db = firebase.firestore();
    const postId  = useSelector(postId);
/* The code is almost identical to MessageShow.js, it's just that we add a .doc(postId)*/
    const [InPostShow] = useCollection( 
      db
      .collection("front-message")
      .doc(postId)
      );
return ( 

{InPostShow?.docs.map((doc) => {
         const { title, message, photoURL, name} = doc.data()

       return (            
<p>{tile}</p>
<p>{message}</p>
  );
})}


    )
}

Enter fullscreen mode Exit fullscreen mode

📰 Reply

The system is really the same as CreatePost.js and ShowMessage.js

🥖 Et voilà !

You've finished your post and reply system
, now all you have to do is put css ✨?

Donations-Support

Bitcoin Ethereum
3FahtNWC4tmZh1B72vz44TvBN2jHaQSnh4 0x7cad12dfd11bce3f29b96260b4739caa32c89a86

Github

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.