Skip to content

Latest commit

 

History

History
160 lines (135 loc) · 2.57 KB

usecontext-usereducer.md

File metadata and controls

160 lines (135 loc) · 2.57 KB

Context & useReducer

Example

const initialState = {
  todos: []
}
const ADD_TODO = 'ADD_TODO'
const REMOVE_TODO = 'REMOVE_TODO'
const TOGGLE_DONE = 'TOGGLE_DONE'
const addTodo = label => ({
  type: ADD_TODO,
  payload: { label }
})

const removeTodo = id => ({
  type: REMOVE_TODO,
  payload: { id }
})

const markDone = id => ({
  type: TOGGLE_DONE,
  payload: { id }
})
export default function(state, action) {
  
  const { type, payload } = action
  
  switch(type) {
    case ADD_TODO:
      return {
        todos: state.todos.concat([{
          id: Date.now(),
          label: payload.label,
          done: false
        }])
      }
    case REMOVE_TODO:
      return {
        todos: state.todos.filter(
          todo => todo.id !== payload.id
        )
      }
    case TOGGLE_DONE:
      return {
        todos: state.todos.map(
          todo => todo.id === payload.id
            ? {
              ...todo,
              done: !todo.done
            }
            : todo
        )
      }
    default:
      return state
  }
}
const TodosContext = createContext()
const Provider = ({ children }) => {
  
  const [state, dispatch] = useReducer(reducer, initialState)
  
  const value = {
    todos: state.todos,
    addTodo: label => dispatch(addTodo(label)),
    removeTodo: id => dispatch(removeTodo(id)),
    markDone: id => dispatch(markDone(id)),
  }
  
  return (
    <TodosContext.Provider value={value}>
      {children}
    </TodosContext.Provider>
  )
}
const AddTodo = () => {
  
  const [label, setLabel] = useState('')
  
  const { addTodo } = useContext(TodosContext)
  
  return (
    <>
      <input type='text'
             value={label}
             onChange={e => setLabel(e.target.value)}
             placeholder='Type your todo...'
      />
      <button onClick={() => {
        addTodo(label)
        setLabel('')
      }}>
        Add
      </button>
    </>
  )
}
const TodosList = () => {
  
  const { todos, removeTodo, markDone } = useContext(TodosContext)
  
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}
            className={'todo' + (todo.done ? ' done' : '')}
            onClick={() => markDone(todo.id)}
        >
          {todo.label}
          <button onClick={() => removeTodo(todo.id)}>
            X
          </button>
        </li>
      ))}
    </ul>
  )
}
const TodosApp = () => {
  return (
    <Provider>
      <AddTodo />
      <TodosList />
    </Provider>
  )
}




Prev - useReducer | Next -