아마도 Redux가 필요하지 않을 것입니다. React Context + useReducer hook 사용

I would like to amend this: don't use Redux until you have problems with vanilla React. - Dan Abramov



Dan은 2016년에 이렇게 말했습니다. 이제 React Context와 useReducer 후크가 있으므로 redux의 사용 사례는 매우 최소화됩니다. 이 게시물에서는 Context 및 useReducer 후크를 사용하여 좋은 오래된 할일 목록 예제를 만들 것입니다.

먼저 초기 상태와 작업을 설정해 보겠습니다. 할 일 앱에 추가, 제거 및 토글 완료의 세 가지 작업이 포함되도록 합니다.

const initialState = {
  todoList: []
};

const actions = {
  ADD_TODO_ITEM: "ADD_TODO_ITEM",
  REMOVE_TODO_ITEM: "REMOVE_TODO_ITEM",
  TOGGLE_COMPLETED: "TOGGLE_COMPLETED"
};


이제 작업을 처리하기 위해 감속기 기능을 추가해 보겠습니다.

const reducer = (state, action) => {
  switch (action.type) {
    case actions.ADD_TODO_ITEM:
      return {
        todoList: [
          ...state.todoList,
          {
            id: new Date().valueOf(),
            label: action.todoItemLabel,
            completed: false
          }
        ]
      };
    case actions.REMOVE_TODO_ITEM: {
      const filteredTodoItem = state.todoList.filter(
        (todoItem) => todoItem.id !== action.todoItemId
      );
      return { todoList: filteredTodoItem };
    }
    case actions.TOGGLE_COMPLETED: {
      const updatedTodoList = state.todoList.map((todoItem) =>
        todoItem.id === action.todoItemId
          ? { ...todoItem, completed: !todoItem.completed }
          : todoItem
      );
      return { todoList: updatedTodoList };
    }
    default:
      return state;
  }
};


분해해 봅시다.
  • ADD_TODO_ITEM 작업에서 기존 목록을 펼치고 id (고유한), label (사용자가 입력한 값), completed를 사용하여 목록에 새 할 일 항목을 추가합니다. 깃발.
  • REMOVE_TODO_ITEM 작업에서 ID를 기반으로 제거해야 하는 할일 항목을 필터링하고 있습니다.
  • TOGGLE_COMPLETED 작업에서 모든 할 일 항목을 반복하고 ID를 기반으로 완료된 플래그를 토글합니다.

  • 이제 이를 Context 및 useReducer와 연결해 보겠습니다. TodoListContext 를 만들어 봅시다.

    const TodoListContext = React.createContext();
    

    Provider 의 공급자를 반환하는 TodoListContext 함수를 만들어 보겠습니다.

    const Provider = ({ children }) => {
      const [state, dispatch] = React.useReducer(reducer, initialState);
    
      const value = {
        todoList: state.todoList,
        addTodoItem: (todoItemLabel) => {
          dispatch({ type: actions.ADD_TODO_ITEM, todoItemLabel });
        },
        removeTodoItem: (todoItemId) => {
          dispatch({ type: actions.REMOVE_TODO_ITEM, todoItemId });
        },
        markAsCompleted: (todoItemId) => {
          dispatch({ type: actions.TOGGLE_COMPLETED, todoItemId });
        }
      };
    
      return (
        <TodoListContext.Provider value={value}>
          {children}
        </TodoListContext.Provider>
      );
    };
    


    분해해 봅시다.
  • reducer 함수와 initialState를 useReducer 후크에 전달합니다. 이것은 상태와 디스패치를 ​​반환할 것입니다. 상태에는 initialState가 있고 디스패치는 redux에서와 같이 작업을 트리거하는 데 사용됩니다.
  • 값 개체에는 todoList 상태와 각각 addTodoItem , removeTodoItemmarkAsCompleted 작업을 트리거하는 세 가지 함수 ADD_TODO_ITEM , REMOVE_TODO_ITEMTOGGLE_COMPLETED가 있습니다.
  • TodoListContext 를 사용하여 액세스할 수 있도록 값 개체를 useContext 의 공급자에게 prop으로 전달합니다.

  • 좋습니다. 이제 글로벌 스토어와 감속기가 설정되었습니다. 이제 상점을 사용할 두 개의 구성 요소AddTodoTodoList를 만들어 보겠습니다.

    const AddTodo = () => {
      const [inputValue, setInputValue] = React.useState("");
      const { addTodoItem } = React.useContext(TodoListContext);
    
      return (
        <>
          <input
            type="text"
            value={inputValue}
            placeholder={"Type and add todo item"}
            onChange={(e) => setInputValue(e.target.value)}
          />
          <button
            onClick={() => {
              addTodoItem(inputValue);
              setInputValue("");
            }}
          >
            Add
          </button>
        </>
      );
    };
    

    AddTodo 에서 useContext를 사용하여 TodoListContext를 구독하고 addTodoItem 디스패치 함수를 가져옵니다. 이 구성 요소에는 사용자가 할 일 항목을 입력하는 입력 필드와 목록에 할 일 항목을 추가하는 add 버튼이 있습니다.

    const TodoList = () => {
      const { todoList, removeTodoItem, markAsCompleted } = React.useContext(
        TodoListContext
      );
      return (
        <ul>
          {todoList.map((todoItem) => (
            <li
              className={todoItem.completed ? "completed" : ""}
              key={todoItem.id}
              onClick={() => markAsCompleted(todoItem.id)}
            >
              {todoItem.label}
              <button
                className="delete"
                onClick={() => removeTodoItem(todoItem.id)}
              >
                X
              </button>
            </li>
          ))}
        </ul>
      );
    };
    

    TodoList 구성 요소에서 useContext를 사용하여 TodoListContext를 구독하고 todoList 상태, removeTodoItemandmarkAsCompleted 디스패치 기능을 가져옵니다. todoList를 통해 매핑하고 할 일 항목과 그 옆에 있는 제거(X) 버튼을 렌더링합니다. 항목을 클릭하면 complete로 표시되고 X 버튼을 클릭하면 목록에서 제거됩니다.

    마지막으로 두 구성 요소를 Provider로 래핑해 보겠습니다.

    export default function App() {
      return (
        <Provider>
          <AddTodo />
          <TodoList />
        </Provider>
      );
    }
    


    엄청난. Context 및 useReducer 후크를 사용하여 redux의 대안으로 상태를 관리했습니다. codesandbox 에서 작업 코드를 확인할 수 있습니다.

    그게 다야, 여러분, 이 블로그 게시물을 읽어주셔서 감사합니다. 도움이 되셨기를 바랍니다. 질문과 제안을 댓글로 남겨주세요.

    좋은 웹페이지 즐겨찾기