How to make a simple post and reply system with React, Firebase, Redux
Tags: react, firebase, firestore, redux
Published: 2021-12-05 08:33:15

![TRIO](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ho9dtpi1aime0zejvbt.jpg)

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

```
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"
```

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

##### Router.js
```javascript
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>

```

# ➕ 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.

```javascript
    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>
    )
```

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7mpi2rsl2psd3wlfl12a.PNG)

# 📖 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.

```javascript 
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}
  />
))}

)
```

###### 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.

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

return (
<img src={photoURL}>
<p> {title} </p>
<p> {name} </p>
)
```

# 🚗 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

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

Then you create a new file `'PostSlice.js'`

```javascript 

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;


```

We modify our `` ' index.js ' ``
```javascript 
/* 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')
);

```
Now, we come back to our `MessageShow.js` file

```javascript 

 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>
)

```

We now come back to our ``app (router.js)``
```javascript
/* 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} />
)
```

# 📜 InPost

Create a new file named ``InPost.js``

```javascript
/* 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>
  );
})}


    )
}

```

# 📰 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](https://github.com/DenSpec)