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
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.
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:
📖 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}
/>
))}
)
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>
)
🚗 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,
},
});
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;
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')
);
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>
)
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} />
)
📜 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>
);
})}
)
}
📰 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 |
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.