How to make Trello system clone whit React, Firebase, Redux.
Tags: react, firebase, firestore, redux
Published: 2021-12-05 14:08:18



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zgu7vauomoly6nw3cpt.jpg)
Hi ! Today we will see How to make Trello system clone whit R-F-R

## In this tutorial there will be:
- Create a project then entered it whit Redux
- Create a card in the project then put lists

## File structure

```
src 
  └──app
     └── components 
        ├── Home.js
        ├── InProject.js
        ├── ShowCards.js
  └──store
     ├── store.js
     ├── ProjectSlice.js

   ├── app(router).js

```

## Packages
Install the packages below :

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

## Router
Create the following files in your src folder:

- ``Home.js``
- ``InProject``

Then put them in the router.

###### app(router).js

```javascript
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import home from './Home'
import project from './InProject'
<Router>
         <Switch>
          <Route exact path="/" component={home} />
          <Route exact path="/project" component={project} />
        </Switch>
        </div>
</Router>
```

## Create a project 

Go to the Home.js file
We are going to create a new function which will be called {createProject}. With Firestore, we will create a new document in the 'project' collection.
In it, we will put two different fields, one for the creation date ``timestamp``, and the other titleProject which will be the value of the input (defined by a Ref)

###### Home.js

```javascript 
    const inputTitleProject = useRef(""); 

    const db = firebase.firestore();
    const createProject = useCallback(async event => {
        event.preventDefault();
        if (inputTitle.current.value !== "") {
            db.collection("project").add({
              timestamp: firebase.firestore.FieldValue.serverTimestamp(),
              titleProject: inputTitle.current.value,
            }); 
        }
    })

    return (
/* the onSubmit will execute the "createProject" function. */    
   <form onSubmit={createProject}>
    <input
    ref={inputTitleProject}
    placeholder="Your title project"
    >
    <button type="submit">
    Create the project !
    </button>
    </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/9gon0ar5gwkwp5d8egrm.PNG)

## Display all project

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

To be able to read the project, we will create a file named ``ShowProject.js``, we will display the project inside.

###### Home.js
```javascript
import { useCollection } from "react-firebase-hooks/firestore"
import ShowProject from './ShowProject.js'
    const db = firebase.firestore();
    const [listproject] = useCollection(
      db
      .collection("project")
      );  

return( 

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

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

  <ShowProject
  key={doc.id}
  id={doc.id}
  titleProject={doc.data().titleProject}
  />
))}
)
```

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

###### ShowProjects.js
```javascript
function ShowProject({id, titleProject}) {

return (
<div>
<p>{titleProject}</p>
</div>
)
```

# 🐱‍🚀 Redux joinded the chat 

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

###### store.js
```javascript
/* We import the configureStore from redux */
import { configureStore } from "@reduxjs/toolkit";
import projectSlice from "./ProjectSlice";
export const store = configureStore({
  reducer: {
    project: projectSlice,
  },
});
``` 
Then you create a new file ``ProjectSlice.js``

###### ProjectSlice.js
```javascript
import { createSlice } from "@reduxjs/toolkit";

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

export const projectSlice = createSlice({
  name: "project",
  initialState,
  reducers: {
    setProject: (state, action) => {
      state.projectId = action.payload.projectId;
      state.projectName = action.payload.projectName;
    },
  },
});

export const { setProjectInfo } = projectSlice.actions;

export const selectProjectId = (state) => state.project.projectId;
export const selectProjectName = (state) => state.project.projectName;

export default projectSlice.reducer;
```

We modify our ``index.js``

###### 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 ``ShowProject.js`` file

###### ShowProject.js
```javascript

 function ShowProject({id, title, name, photoURL}) {
 const setProject = () => {
        dispatch(
          setProjectInfo({
            projectId: id,
          })
        );

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

/* We modify our div, and when we click on it, it executes the 'setProject' function
We also define the cursor as a pointer
*/

<div onClick={setProject} style={{cursor: 'pointer'}}>
<p> {title} </p>
</div>
)

```

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

###### app(router).js
```javascript
/* You just add these two little lines.
We can  put the id in the router. When it is on the url /project/{id}/, it will display the component 'InProject.js'
*/

import InProject from './InProject.js'
return ( 
          <Route exact path="/project/:id" component={InProject} />
)
```

# In Project
### Create Card

Go to the ``InProject.js`` file
The system will be almost the same as for the ``Home.js``
We are going to create a new function which will be called {createCard}. With Firestore, we will create a new document in the collection ``project/{projectId}/card/``
In it, we will put two different fields, one for the creation date ``timestamp``, and the other titleCard which will be the value of the input (defined by a Ref)

###### InProject.js

```javascript 

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

    const inputTitleCard = useRef(""); 
    const db = firebase.firestore();
    const projectId  = useSelector(postId);
    const createCard = useCallback(async event => {
        event.preventDefault();
        if (inputTitle.current.value !== "") {
            db.collection("project").doc(projectId).collecton("card").add({
              timestamp: firebase.firestore.FieldValue.serverTimestamp(),
              titleProject: inputTitle.current.value,
            }); 
        }
    })

    return (
/* the onSubmit will execute the "createCard" function. */    
   <form onSubmit={createCard}>
    <input
    ref={inputTitleCard}
    placeholder="Title of your card"
    >
    <button type="submit">
    Create the Card !
    </button>
    </form>
    )

```

### Read Card

It is almost identical to ``Home.js``
With the useCollection function, we can choose any collection. For this case, we're going to use the ``project/{projectId}/card`` collection. Then, we will make a docs.map, where we will put all the fields.

###### InProject.js
```javascript
import { useCollection } from "react-firebase-hooks/firestore"
    const db = firebase.firestore();
    const [listcard] = useCollection(
      db
      .collection("project")
      .doc(projectId)
      .collection("card")
      );  

return( 

         {frontmessagez?.docs.map((doc) => {
         const { titleCard} = doc.data()
       return (            
<>
<div>
   <p>  {titleCard} </p>
</div>
</>

  );
})}
```

### CreateList & ReadList
The system is the same as for the ``Home.js`` & ``InProject.js``

# 🥖 Et voilà ! 

You've finished your Trello system clone whit React, Firebase, Redux.
, now all you have to do is put css ✨?

# Donations-Support

| Bitcoin | Ethereum | 
|-----------------|-----------------|:-------------| 
``3FahtNWC4tmZh1B72vz44TvBN2jHaQSnh4`` | ``0x7cad12dfd11bce3f29b96260b4739caa32c89a86``   | 

[Github](https://github.com/DenSpec)