目录

1. store.ts

2. reducer.ts

3. ReduxProvider.tsx

4. mapStateToProps.ts

5. mapDispatchToProps.ts

6.  Todo组件(最外层包ReduxProvider

7. Todo组件里面涉及的子组件

1) TodoInput.tsx

2) TodoList.tsx

3) TodoItem.tsx

8. App组件使用Todo组件


1. store.ts

参考网站: GitHub - zalmoxisus/redux-devtools-extension: Redux DevTools extension.

下载谷歌扩展插件的地址: react-redux-devtools: react-devtools-v3react-devtools-v4redux-devtools

import { applyMiddleware, combineReducers, legacy_createStore as createStore } from 'redux';
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from 'redux-thunk';
import { todos, visibilityFilter } from './reduer';

// 使用 redux-devtools
const composeEnhancers = composeWithDevTools({
    // options like actionSanitizer, stateSanitizer
  });
  // 使用 redux-thunk 中间件
  const enhancer = composeEnhancers(applyMiddleware(thunk));
export default createStore(combineReducers({ todos, visibilityFilter }), enhancer);

2. reducer.ts

export const visibilityFilter = (state = 'SHOW_ALL', action) => {
    switch (action.type) {
      // 设置显示类型(所有、完成、未完成)
      case 'SET_VISIBILITY_FILTER':
        return action.filter
  
      // 默认是 SHOW_ALL
      default:
        return state
    }
  }

  // 新增列表数据和改变数组数据
  // 将业务逻辑拆分到一个单独文件中,方便进行状态管理
export interface StateProps {
    id: number;
    text: string;
    isFinished: boolean;
  }
  export interface ActionProps {
    type: string;
    [key: string]: any;
  }
export const todos = (state: StateProps[] | [], action: ActionProps) => {
    console.log(state, action);
    switch (action.type) {
      case "ADD":
        return [...state, action.todo];
      case "CHANGESTATUS":
        return state.map((item) => {
          if (item.id === action.id) {
            return Object.assign({}, item, { isFinished: !item.isFinished });
          }
          return item;
        });
      default:
        return state || [];
    }
  };

3. ReduxProvider.tsx

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

const ReduxProvider = (props) => {
  return <Provider store={store}>{props.children}</Provider>;
};

export default  ReduxProvider

4. mapStateToProps.ts

// 不同类型的 todo 列表
const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case "SHOW_ALL": // 全部显示
      return todos;
    case "SHOW_FINISHED":
      return todos.filter((t) => t.isFinished);
    case "SHOW_NOT_FINISH":
      return todos.filter((t) => !t.isFinished);
    default:
      return todos;
  }
};

const mapStateToProps = (state) => {
  return {
    // 根据完成状态,筛选数据
    todoList: getVisibleTodos(state.todos, state.visibilityFilter),
  };
};

export default mapStateToProps;

5. mapDispatchToProps.ts

import { StateProps } from "./reduer";

const mapDispatchToProps = (dispatch) => {
    const changeTodo = (id: number) => {
      dispatch({ type: "CHANGESTATUS", id });
    };
    // 添加todo
    const addTodo = (todo: StateProps) => {
      dispatch({ type: "ADD", todo });
    };
  
    // 显示已完成的
    const showFinished = () => {
      dispatch({ type: "SET_VISIBILITY_FILTER", filter: 'SHOW_FINISHED' });
    }
    // 显示未完成的
    const showNotFinish = () => {
      dispatch({ type: "SET_VISIBILITY_FILTER", filter: 'SHOW_NOT_FINISH' });
    }
    // 显示全部完成的
    const showAll = () => {
      dispatch({ type: "SET_VISIBILITY_FILTER", filter: 'SHOW_ALL' });
    }
  
  
    return {
      addTodo,
      // 切换完成状态
      changeTodo,
      showFinished,
      showNotFinish,
      showAll,
    };
  };

  export default mapDispatchToProps

6.  Todo组件(最外层包ReduxProvider

import React from "react";
import ReduxProvider from "./ReduxProvider";
import { TodoInput } from "./TodoInput";
import { TodoList } from "./TodoList";

// 父组件
export const Todo = () => {
    return (
        <ReduxProvider>
            <TodoInput />
            <TodoList  />
        </ReduxProvider>
    )
}

7. Todo组件里面涉及的子组件

1) TodoInput.tsx

import React from "react";
import { useState } from "react";
import mapStateToProps from "./mapStateToProps";
import mapDispatchToProps from "./mapDispatchToProps";
import { connect } from "react-redux";

// 子组件
const TodoInput0 = (props) => {
  const [text, setText] = useState("");
  const { addTodo, showAll, showFinished, showNotFinish } = props;
  const handleChangeText = (e: React.ChangeEvent) => {
    setText((e.target as HTMLInputElement).value);
  };
  const handleAddTodo = () => {
    if (!text) return;
    addTodo({
      id: new Date().getTime(),
      text: text,
      isFinished: false,
    });
    setText("");
  };
  return (
    <div className="todo-input">
      <input
        type="text"
        placeholder="请输入代办事项"
        onChange={handleChangeText}
        value={text}
      />
      <button style={{ marginLeft: "10px" }} onClick={handleAddTodo}>
        +添加
      </button>
      <button style={{ marginLeft: "10px" }} onClick={showAll}>
        show all
      </button>
      <button style={{ marginLeft: "10px" }} onClick={showFinished}>
        show finished
      </button>
      <button style={{ marginLeft: "10px" }} onClick={showNotFinish}>
        show not finish
      </button>
    </div>
  );
};

const TodoInput = connect(mapStateToProps, mapDispatchToProps)(TodoInput0);
export { TodoInput };

2) TodoList.tsx

import React from "react";
import { TodoItem } from "./TodoItem";
import _ from "lodash";
import { connect } from "react-redux";
import mapStateToProps from "./mapStateToProps";
import mapDispatchToProps from "./mapDispatchToProps";

const TodoList0 = (props) => {
  const { todoList } = props;

  return (
    <div className="todo-list">
      {_.map(todoList, (item) => (
        <TodoItem key={_.get(item, "id")} todo={item || {}} />
      ))}
    </div>
  );
};

const TodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList0);
export { TodoList };

3) TodoItem.tsx

import React from "react";
import _ from "lodash";
import { connect } from "react-redux";
import mapStateToProps from "./mapStateToProps";
import mapDispatchToProps from "./mapDispatchToProps";

// 孙子组件
const TodoItem0 = (props) => {
  const { todo, changeTodo } = props;
  // 改变事项状态
  const handleChange = () => {
    changeTodo(_.get(todo, "id"));
  };
  return (
    <div className="todo-item">
      <input
        type="checkbox"
        checked={todo.isFinished}
        onChange={handleChange}
      />
      <span
        style={{ textDecoration: todo.isFinished ? "line-through" : "none" }}
      >
        {todo.text}
      </span>
    </div>
  );
};
const TodoItem = connect(mapStateToProps, mapDispatchToProps)(TodoItem0);
export { TodoItem };

8. App组件使用Todo组件

import React from "react";
import { Todo } from "./reduxConnectProvider/Todo";

const App: React.FC = () => {
  return (
    <>
      <Todo />
    </>
  );
};

export default App;

效果示意图

redux-devtools谷歌扩展插件的使用示例-LMLPHP

11-12 06:22