One of the ways to use Context API
Tags: react, javascript, typescript, contextapi
Published: 2022-11-17 06:44:32

As you know a lot of developers replaced redux with react context feature. So I want to show you how I am using it in my products.

We will create a Todo list using context API (based on typescript). 


I will use bootstrap for design._
_![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j5u709lmhyhjz5s8m9lc.png)

_Final view of our code._

## Let's get started!

At first, we must create our context in the `contexts` folder.

`TodoContext.ts`
```typescript
import { createContext } from "react";

export interface ITodo {
    name: string;
    completed: boolean;
}

interface ITodoContext {
    data: ITodo[];
    updateData: Function;
}

export const TodoContext = createContext<ITodoContext>({
    data: [],
    updateData: (data: ITodo[]) => {
        throw new Error('updateData not implemented')
    }
})
```

Here we can see that we are creating an interface for todo items, and also for todo context.

My context has two values, the first one is the data that it must contain and the second one is the function that will update the data. 


After creating context we must create a provider for it.
We are creating it in the `providers` folder.

`TodoProvider.tsx`

```tsx
import {FC, ReactNode, useState} from "react";
import {ITodo, TodoContext} from "../contexts/TodoContext";

interface ITodoProvider {
    children: ReactNode
}

export const TodoProvider:FC<ITodoProvider> = ({children}) => {

    const [data, setData] = useState<ITodo[]>([]);

    const updateData = (data: ITodo[]) => {
        setData(data);
    }

    return (
        <TodoContext.Provider value={{data, updateData}}>
            {children}
        </TodoContext.Provider>
    )
}
```
In our todo provider, we will create and append the initial state for todo data. Also, we must create a function for handling data updates and appending it to our state.

Now we can start to use our created context API in our product.

What we must do:

- Render Todo List.
- Create Todo Item.
- Delete Todo Item.

So let's do it step by step

**Render Todo List**
Idea is to render the table with our todo data.

We will create a `TodoList.tsx` file in the `components` folder.

```tsx
export const TodoList = () => {
  const {data: todoData} = useContext(TodoContext);

  return (
    <div className="container">
      <div className="d-flex justify-content-between" >
        <div className="py-3">
          <h3>Todo List</h3>
        </div>
      </div>
      <table className="table table-striped table-dark">
        <thead>
          <tr>
            <td>Name</td>
            <td width="200">Status</td>
            <td width="150" align="right">Action</td>
          </tr>
        </thead>
        <tbody>
        {
          todoData?.map((item: ITodo, index) => (
            <tr key={`todo-${index}`}>
              <td>{item.name}</td>
              <td>
                {item.completed 
                  ? <span className="badge badge-info">Completed</span> 
                  : <span className="badge badge-secondary">Not Completed</span>
                }
              </td>
            </tr>
          ))
        }
        </tbody>
      </table>
    </div>
  )
}
```

Here you can see that we are using reacts `useContext` hook for getting our data from context.

`const {data: todoData} = useContext(TodoContext);`

So we will have always up-to-date data that we are getting from 
`TodoContext`. 

Of course, it will be always empty, so we must add create functionality for it.

Lets create a simple form.

```tsx
<form ref={formRef} className="py-3 d-flex justify-content-between" onSubmit={handleCreate}>
    <input type="text" name="name" className="form-control" />
    <button type="submit" className="btn btn-primary mx-1">Add</button>
</form>
```

We must create `handleCreate` function in our component for detecting submitting in form.

```tsx

const {data: todoData, updateData: updateTodoData} = useContext(TodoContext);

const handleCreate = (event: React.SyntheticEvent) => {
  event.preventDefault();
  const {target} = event as typeof event & {target: {name: { value: string };}}
  const name = target.name.value;
  updateTodoData([
    ...todoData,
    {
      name: name,
      completed: false
    }
  ])
  formRef?.current?.reset();
}
```

Here you can see that we added updateData which we are taking from our context, and using it as updateTodoData for creating and saving new todo item.

Thats it. Now on submitting form it will create and render new item in our todo list.

By the same logic we can create delete functionality also.

```tsx
const handleDelete = (name: string) => {
  const payload = todoData.filter(item => item.name !== name)
  updateTodoData(payload);
}
```

We are taking the name and filtering our array by it.
After it, we are using our `updateTodoData` function and update our array.

You can check the repository [here](https://github.com/SoxPan/todo-list-context)

And how you are using Context API in your applications?