All right! Our firebase is finally set up. Lets make a way to add tasks to our list. We can create a simple form to add items to the list. The submit button will push the tasks up to our firebase. Head over to the file App.js and add the following:

import {addTaskToFirebase, removeTaskFromFirebase} from './firebase' export default class App extends Component { render() { return (

<div>

<div className="App">

<header className="App-header">

<img src={logo} className="App-logo" alt="logo" />

<h1 className="App-title">Welcome to React</h1>

</header>

<p className="App-intro">

To get started, edit <code>src/App.js</code> and save to reload. </p>

</div>

<div>

<form onSubmit={(e) => {

e.preventDefault()

addTaskToFirebase(e.target.task.value)}}>

<input type="text" name="task" />

<input type="submit" name="add task" />

</form>

</div>

<div>

<h2> Todo:</h2>

<ul>

we will map over our store later!

</ul>

</div>

</div>

);

}

}

Great!

Back in your firebase project page click on the database item in the left menu bar. On the top tab click on rules. Set the read and write rules to true so we can start adding tasks to our todo list. Don’t worry about the massive security issues we have right now, we can change the rules back later.

Now we run npm start from our tasks bar and we are able to sort of add tasks to our todo list. Nothing happens after we click add task on the page. But if we go back to the database tab in your firebase project, the tasks you add should be showing up over in your real time database.

This is great and all but we would probably like them to show up on the page. On to the store! In the tutorial I’m going to gloss over the details of implementing a redux store, if you would like more information check out https://egghead.io/courses/getting-started-with-redux. Make a new file in the src directory store.js. At the top we will handle our imports:

import { createStore, applyMiddleware } from 'redux'

import database from './firebase'

import thunkMiddleware from 'redux-thunk'

First we will make an action to fetch all of our tasks from firebase. The code for that will look something like this.

/**

* ACTION TYPES

*/

const GET_TASKS = 'get tasks' /**

* ACTION CREATORS

*/

export const getTasks = (tasks) => ({type: GET_TASKS, tasks}) /**

* THUNKS

*/

export function getTasksThunk() {

return dispatch => {

const tasks = [];

database.ref(`/`).once('value', snap => {

snap.forEach(data => {

let task = data.val();

tasks.push(task)

})

})

.then(() => dispatch(getTasks(tasks)))

}

}

The action constant and action creators are pretty standard to any redux store so lets talk about the Thunk. Thunk is just a funny word that allows us to dispatch asynchronous functions to stores instead of only objects. This is available to us through thunk middleware. We use it here to make an async call our firebase, get all of the tasks inside of it, and then dispatch the lot to our redux store. This will happen through the reducer we create right after it here:

/**

* REDUCER

*/

function Reducer (state = [], action) {

switch (action.type) {

case GET_TASKS:

return action.tasks

default:

return state

}

} export default createStore(Reducer, applyMiddleware(thunkMiddleware))

The last line creates our store with our reducer. We export it so we can use it with the rest of our application. Open up our main index file and add a few lines to it to import Provider from react-redux. We use provider to give all of our components access to our redux store(and our firebase through it).

...

import store from './store'

import { Provider } from 'react-redux' ReactDOM.render(

<Provider store={store}>

<App />

</Provider>,

document.getElementById('root'));

...

Open up the App component again, and lets connect our store. Import the store and our getTaskThunk at the top of the file. We will be using to the connect function to well… connect our app to the store. More information on connect can be found in this great article over here https://medium.com/mofed/reduxs-mysterious-connect-function-526efe1122e4.

import { connect } from 'react-redux'

import { getTasksThunk } from './store'

In the jsx of the component add this line to display all of our tasks.

...

<div>

<h2> Todo:</h2>

<ul>

{this.props.tasks.map(item => <li key={item.id}>{item.task}<button

onClick={() => removeTaskFromFirebase(item.id)}>x</button></li>)} </ul>

</div>

...

Where are these tasks coming from? Glad you asked we get them from the store through the connect function it looks something like this:

const mapState = state => ({

tasks: state

})

const mapDispatch = dispatch => {

dispatch(getTasksThunk())

return {

}

}

export default connect(mapState, mapDispatch)(App);

All we have on our state is our tasks, so we can just map the task prop to our entire state. The mapDispatch function gives our component functions that have the ability to send information to the store. Because we want this one to execute on load, we place it outside of the returned object. Finally we connect the the component with the store on the last line and export it as the default. Your linter should yell at you at this point, make sure to delete the current export default in front of the class declaration near the top of the file.

Run another npm start and wallah! The tasks you’ve previously added to your firebase should appear. Try adding another one. Nothing >.>, but on refresh it shows up as expected. Lets fix that with some nifty event listeners provided to us by firebase.

Open up your store.js file and add the following:

/**

* ACTION TYPES

*/

...

const ADD_TASK = 'add task'

const REMOVE_TASK = 'remove task' /**

* ACTION CREATORS

*/

...

export const addTask = (task) => ({type: ADD_TASK, task})

export const removeTask = (task) => ({type: REMOVE_TASK, task}) /**

* LISTENERS

*/

export function watchTaskAddedEvent(dispatch) {

database.ref(`/`).on('child_added', (snap) => { dispatch(addTask(snap.val()));

});

} export function watchTaskRemovedEvent(dispatch) {

database.ref(`/`).on('child_removed', (snap) => {

dispatch(removeTask(snap.val()));

});

}

Firebase allows your application to listen for events and execute callbacks when the event fires. For a complete list of listeners check out the documentation here https://firebase.google.com/docs/database/admin/retrieve-data. We will be using the child_added and child_removed events. Whenever a item is added to our firebase it will dispatch the addTask function with the data the realtime database has just received. Likewise it will dispatch removeTask whenever an item is deleted.

Update the reducer to handle these new actions:

/**

* REDUCER

*/

function Reducer (state = [], action) {

switch (action.type) {

case GET_TASKS:

return action.tasks

case ADD_TASK:

return [...state, action.task]

case REMOVE_TASK:

return state.filter(task => task.id !== action.task.id)

default:

return state

}

}

All that left to hook up our new listeners to the app component. Open up App.js and add import the two new functions.

import { getTasksThunk, watchTaskAddedEvent, watchTaskRemovedEvent } from './store'

Add them to your mapDispatch and you are all set!

const mapDispatch = dispatch => {

dispatch(getTasksThunk())

watchTaskAddedEvent(dispatch)

watchTaskRemovedEvent(dispatch)

return {

}

}

Run npm start once more and bam! Our app adds and removes tasks on command. But you could do that before firebase. Open up another tab at the same address and marvel at how each page updates when you add or remove tasks!

Thanks for reading!