Giter Club home page Giter Club logo

react-hooks-todo-app's Introduction

React Hooks Todo App

A trial to achieve a correct approach. Trying to get rid off using Redux, make contexts more useful with useReducer and make components "easy-to-test simple functions".

Edit react-usecontext-todo-app


A highly decoupled, testable TodoList app that uses React hooks.

This is a training repo to learn about new hooks feature of React and creating a testable environment.

  • Zero-dependency
  • No class components
  • Uses Context to share a global state
  • Uses useReducer to manage state actions
  • useState to create local state
  • Decoupled state logic (Actions)
  • Testable components (Uses Jest + Enzyme for tests)
  • Custom Hooks for persisting state.

For better approaches please open Pull Requests

Summary

1. Context:

The main approach was to get rid off Redux and use React Contexts instead. With the composition of useState, useContext I created a global state. And passed it into a custom hook called useTodos. useTodos curries useState output and generates a state manager which will be passed into TodoContext.Provider to be used as a global state.

function App() {
  // create a global store to store the state
  const globalStore = useContext(Store);

  // `todos` will be a state manager to manage state.
  const [state, dispatch] = useReducer(reducer, globalStore);

  return (
    // State.Provider passes the state and dispatcher to the down
    <Store.Provider value={{ state, dispatch }}>
      <TodoList />
      <TodoForm />
    </Store.Provider>
  );
}

2. The Reducer:

The second approach was to seperate the main logic, just as the actions of Redux. But these are fully functional, every function returns whole state.

// Reducer is the classical reducer that we know from Redux.
// used by `useReducer`
export default function reducer(state, action) {
  switch (action.type) {
    case "ADD_TODO":
      return {
        ...state,
        todos: [...state.todos, action.payload]
      };
    case "COMPLETE":
      return {
        ...state,
        todos: state.todos.filter(t => t !== action.payload)
      };
    default:
      return state;
  }
}

3. State and Dispatcher

I reach out state and dispathcer of context using useContext and I can reach to the actions.

import React, { useContext } from "react";
import Store from "../context";

export default function TodoForm() {
  const { state, dispatch } = useContext(Store);
  // use `state.todos` to get todos
  // use `dispatch({ type: 'ADD_TODO', payload: 'Buy milk' })`

4. Persistence with custom hooks:

I created custom hooks to persist state on localStorage

import { useEffect } from "react";

// Accepts `useContext` as first parameter and returns cached context.
export function usePersistedContext(context, key = "state") {
  const persistedContext = localStorage.getItem(key);
  return persistedContext ? JSON.parse(persistedContext) : context;
}

// Accepts `useReducer` as first parameter and returns cached reducer.
export function usePersistedReducer([state, dispatch], key = "state") {
  useEffect(() => localStorage.setItem(key, JSON.stringify(state)), [state]);
  return [state, dispatch];
}

The App function will be:

function App () {
  const globalStore = usePersistedContext(useContext(Store));

  // `todos` will be a state manager to manage state.
  const [state, dispatch] = usePersistedReducer(useReducer(reducer, globalStore));

5. Everything is testable decoupled:

The last but most important part of the approach is to make all the parts testable. They don't tie to eachother which makes me to write tests easily.

License

MIT

react-hooks-todo-app's People

Contributors

f avatar halitogunc avatar selcukitmis avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.