React + Redux = React + Context
Tags: react, javascript, webdev, frontend
Published: 2019-12-30 12:59:34

---
title: React + Redux = React + Context
published: true
description: Context implementation in React App.
tags: #react #javascript #webdev #frontend
---

I know, many articles are already talking about whether or not to replace Redux with Context. If yes, what are the tradeoffs, etc? But I don't think this is one of them.
> 	This is simply for fun 😁. But still, you can try this in your pet projects 😉.

> Hoping you have installed NodeJS, npm, and npx

First, let's set up a basic react template. Go to your favorite directory you'd like to play with.  Run, 
`npx create-react-app fooapp`

Change the app directory `cd fooapp`.

Now start the app, `npm start`. I hope the app has started and is opened in your browser at `http://localhost:3000/`.

Create a folder **store**  under *src*.
`cd src && mkdir store`

Create two files under `store`. `index.js` and  `handlers.js`

In `index.js` file under `store`. We'll create a Context.

```jsx
/** index.js **/
import React from "react";
import PropTypes from "prop-types";

// Import all handlers
import * as handlers from "./handlers";

// Default state
const initialState = { todos:[] };

// Export the context
export const Context = React.createContext({ state: initialState, handlers });

// Export the provider
export const Provider = ({ children }) => {
  // This will be our global state
  const [state, setState] = React.useState(initialState);

  // Modify our hanlders with state and setState
  // Thanks Jose for this one 👍
   const modHandlers = Object.keys(handlers).map(key => handlers[key](state, setState))

  // Feed the state and modified handlers to the provider
  return (
    <Context.Provider value={{ state, handlers: modHanlders }}>
      {children}
    </Context.Provider>
  );
};

Provider.propTypes = {
  children: PropTypes.children.isRequired
};
```
<br/>

Let's create handlers to add / remove todo's from the list. In `store/handlers.js`.
```jsx
/* handlers.js*/
export const addTodo = (state, setState) => todo => {
  state.todos.push(todo);
  setState({ ...state });
}

export const removeTodo = (state, setState) => i => {
  delete state.todos[i];
  setState({ ...state });
};
```
<br/>

Update `src/index.js` file. Adding the following contents.
```jsx
// src/index.js
import React from "react";
import ReactDOM from "react-dom";

import Todo from "./components/Todo";
import { Provider } from "./store";

function App() {
  return (
    <Provider>
      <div className="App">
        <h2 className="apptitle">Todo List</h2>
        <Todo />
      </div>
    </Provider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

```
> Don't mind if it throws an error. We will update it.

Create a folder `components`under `src` directory. Add the three files to it `Todo.js`, `TodoField.js` & `TodoItem.js`.

In your `components/Todo.js` file create a component. That holds the todo list.
```jsx
// components/Todo.js
import React from "react";

import TodoItem from "./TodoItem";
import TodoField from "./TodoField";
import { Context } from "../store";

const Todo = props => {
  // Get the state from Context using useContext hook
  const { state } = React.useContext(Context);

  return (
    <div>
      <TodoField />
      <ul>
        {state.todos.map((todo, i) => (
          <TodoItem value={todo} index={i} />
        ))}
      </ul>
    </div>
  );
};

export default Todo;
```
The error should've been gone by now. 

In your `components/TodoField.js` add the following code.
```jsx
// components/TodoField.js
import React from "react";

import { Context } from "../store";

const TodoField = () => {
  const [todo, setTodo] = React.useState(null);

  // Import the handlers from context
  const { handlers } = React.useContext(Context);

  // Handles form and other things
  const handleSubmit = e => {
    e.preventDefault();
    // Add the todo to the store
    handlers.addTodo(todo);
  };

  const handleChange = e => {
    setTodo(e.target.value);
  };

  // Form with field and submit button
  return (
    <form onSubmit={handleSubmit} onChange={handleChange}>
      <input type="text" value={todo} required />
      <input type="submit" value="Add Todo" />
    </form>
  );
};

export default TodoField;
```
<br/>

In your `components/TodoItem.js` add the following code.
```jsx
// components/TodoItem.js
import React from "react";

import { Context } from "../store";

const TodoItem = ({ value, index }) => {
  const { handlers } = React.useContext(Context);
  const removeFromTodo = e => {
    handlers.removeTodo(index);
  };

  return (
    <li>
      {value} <button onClick={removeFromTodo}>x</button>
    </li>
  );
};

export default TodoItem;
```

After adding all the files. Your app should be working like this.
![Todo List App](https://i.imgur.com/zHiKyU1.gif)

All the data is manipulated from the single store and manipulated using handlers.

> You could use get and set method in Lodash for complex JSON object operations. 
> PS: The above method can also handle async operations based on Promise.

The implementation is in [codesandbox](https://codesandbox.io/s/fooapp-33hpq).
Happy Coding. 👩‍💻👨‍💻.... 😀