react hooks和redux状态管理结合使用举例

240 阅读2分钟

当使用 redux-toolkitredux-actionsreselect 和 Hooks 时,下面是一个例子,演示如何在 React 中使用它们来创建一个完整的 Redux 工作流。本例子创建一个 TODO 应用,其中包含一个 todos state,用于存储待办事项。

1. 安装相关依赖

安装 reduxreact-reduxredux-toolkitredux-actionsreselect

npm install --save redux react-redux @reduxjs/toolkit redux-actions reselect

2. 创建 Redux Store

src 目录下创建一个 store.js 文件,并使用 redux-toolkit 创建 Redux Store。

import { configureStore } from '@reduxjs/toolkit';
import todosReducer from './todosSlice';

const store = configureStore({
  reducer: {
    todos: todosReducer,
  },
});

export default store;

上述代码使用 configureStore 函数创建了一个 Redux Store,并将 todosReducer 添加到了 Store 中。

3. 创建 Redux Reducer

src 目录下创建一个 todosSlice.js 文件,并使用 redux-toolkit 创建 Redux Reducer。

import { createSlice } from '@reduxjs/toolkit';

const todosSlice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    addTodo: (state, action) => {
      const { id, text } = action.payload;
      state.push({ id, text, completed: false });
    },
    toggleTodo: (state, action) => {
      const todo = state.find(todo => todo.id === action.payload);
      todo.completed = !todo.completed;
    },
    deleteTodo: (state, action) => {
      return state.filter(todo => todo.id !== action.payload);
    },
  },
});

export const { addTodo, toggleTodo, deleteTodo } = todosSlice.actions;
export default todosSlice.reducer;

上述代码使用 createSlice 函数创建了一个 Redux Reducer,并包含了三个 actions:addTodotoggleTododeleteTodo。每个 action 都会返回一个新的 state,而不会直接修改原始 state。

4. 创建 Redux Selectors

src 目录下创建一个 selectors.js 文件,并使用 reselect 创建 Redux Selectors。

import { createSelector } from 'reselect';

const getTodos = state => state.todos;

export const getCompletedTodos = createSelector(
  [getTodos],
  todos => todos.filter(todo => todo.completed)
);

export const getIncompleteTodos = createSelector(
  [getTodos],
  todos => todos.filter(todo => !todo.completed)
);

上述代码使用 createSelector 函数创建了两个 Redux Selectors:getCompletedTodosgetIncompleteTodos。每个 selector 都将 getTodos selector 的结果作为参数,并返回一个新的值。

5. 创建 Redux Actions

src 目录下创建一个 actions.js 文件,并使用 redux-actions 创建 Redux Actions。

import { createAction } from 'redux-actions';

export const addTodo = createAction('ADD_TODO');
export const toggleTodo = createAction('TOGGLE_TODO');
export const deleteTodo = createAction('DELETE_TODO');

上述代码使用 createAction 函数创建了三个 Redux Actions:addTodotoggleTododeleteTodo。这些 actions 会自动创建一个 action creator,并生成一个 type 常量,该常量用于在 reducer 中处理 actions。

6. 创建组件

src 目录下创建一个 TodoList.js 文件,并编写组件代码。

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { addTodo, toggleTodo, deleteTodo } from './actions';
import { getCompletedTodos, getIncompleteTodos } from './selectors';

function TodoList() {
  const dispatch = useDispatch();
  const completedTodos = useSelector(getCompletedTodos);
  const incompleteTodos = useSelector(getIncompleteTodos);

  const handleAddTodo = (e) => {
    e.preventDefault();
    const text = e.target.elements.todo.value;
    dispatch(addTodo({
      id: Date.now(),
      text,
    }));
    e.target.reset();
  };

  const handleToggleTodo = (id) => {
    dispatch(toggleTodo(id));
  };

  const handleDeleteTodo = (id) => {
    dispatch(deleteTodo(id));
  };

  return (
    <div>
      <h1>Todo List</h1>
      <form onSubmit={handleAddTodo}>
        <input type="text" name="todo" placeholder="Add Todo" />
        <button type="submit">Add</button>
      </form>
      <h2>Incomplete</h2>
      <ul>
        {incompleteTodos.map(todo => (
          <li key={todo.id}>
            <span>{todo.text}</span>
            <button onClick={() => handleToggleTodo(todo.id)}>Complete</button>
            <button onClick={() => handleDeleteTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>
      <h2>Completed</h2>
      <ul>
        {completedTodos.map(todo => (
          <li key={todo.id}>
            <span>{todo.text}</span>
            <button onClick={() => handleToggleTodo(todo.id)}>Incomplete</button>
            <button onClick={() => handleDeleteTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoList;

上述代码创建了一个 TodoList 组件,该组件使用了 useDispatchuseSelector Hooks 来与 Redux Store 进行交互。该组件中包含了一个表单,用于添加新的待办事项,并展示了两个列表:未完成的待办事项和已完成的待办事项。每个待办事项都包含了两个按钮:一个用于将待办事项标记为已完成,一个用于将待办事项删除。

最后,在 App.js 文件中使用 TodoList 组件:

import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import TodoList from './TodoList';

function App() {
  return (
    <Provider store={store}>
      <TodoList />
    </Provider>
  );
}

export default App;

上述代码使用 Provider 组件将 Redux Store 传递给 TodoList 组件,使其可以与 Redux Store 进行交互。