iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
0
Modern Web

反正我想學-Web綜合練習紀錄30天系列 第 11

反正我想學10-React-Redux TodoList(下)

  • 分享至 

  • twitterImage
  •  

雖然是Redux TodoList 最後一篇
但發現好像沒有特別解釋程式的部分

原因是這幾天 我都在工作專案中鬼打牆
下了班還要繼續寫

學習跟實作的時間 少很多
文章就水水的

開始前還是要先看推薦一下這篇
也許你不需要 redux
https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367

其中有提到 如果你不知道自己專案需不需要使用redux
很可能就不需要...


今天就來繼續 TodoList

index.js 知道今天的主軸是 TodoApp

import React from "react";
import ReactDOM from "react-dom";

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

import TodoApp from "./TodoApp";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <TodoApp />
  </Provider>,
  rootElement
);

我們可以看出 TodoList 三個階層 AddTodo , TodoList , VisibilityFilters

import React from "react";
import AddTodo from "./components/AddTodo";
import TodoList from "./components/TodoList";
import VisibilityFilters from "./components/VisibilityFilters";
import "./styles.css";

export default function TodoApp() {
  return (
    <div className="todo-app">
      <h1>Todo List</h1>
      <AddTodo />
      <TodoList />
      <VisibilityFilters />
    </div>
  );
}


先看 AddTodo 組件
需要建立一個 input 利用組件內state ,輸入值時onChange 儲存變化,
再創建 button 將本地存好的input value 送出並清空
結尾處 connect 將 addTodo 裡面的action 跟 AddTodo 組件綁再一起

./src/components/AddTodo.js

import React from "react";
import { connect } from "react-redux";
import { addTodo } from "../redux/actions";

class AddTodo extends React.Component {
  constructor(props) {
    super(props);
    this.state = { input: "" };
  }

  updateInput = input => {
    this.setState({ input });
  };

  handleAddTodo = () => {
    this.props.addTodo(this.state.input);
    this.setState({ input: "" });
  };

  render() {
    return (
      <div>
        <input
          onChange={e => this.updateInput(e.target.value)}
          value={this.state.input}
        />
        <button className="add-todo" onClick={this.handleAddTodo}>
          Add Todo
        </button>
      </div>
    );
  }
}

export default connect(
  null,
  { addTodo }
)(AddTodo);
// export default AddTodo;


todoList 為中間顯示 欄位
會收到 Filter 的 action 變更顯示的值 (決定現在該顯示的狀態,all-全部、completed-完成、incompleted-未完成)
show出 資料 算是Todo (細項)的外層

./src/components/todoList.js

import React from "react";
import { connect } from "react-redux";
import Todo from "./Todo";  
import { getTodosByVisibilityFilter } from "../redux/selectors";

const TodoList = ({ todos }) => (
  <ul className="todo-list">
    {todos && todos.length
      ? todos.map((todo, index) => {
          return <Todo key={`todo-${todo.id}`} todo={todo} />;
        })
      : "No todos, yay!"}
  </ul>
);

const mapStateToProps = state => {
  const { visibilityFilter } = state;
  const todos = getTodosByVisibilityFilter(state, visibilityFilter);
  return { todos };
};
// export default TodoList;
export default connect(mapStateToProps)(TodoList);

Todo.js
顯示每一項資料的 及點擊事件

import React from "react";
import { connect } from "react-redux";
import cx from "classnames";
import { toggleTodo } from "../redux/actions";

const Todo = ({ todo, toggleTodo }) => (
  <li className="todo-item" onClick={() => toggleTodo(todo.id)}>
    {todo && todo.completed ? "?" : "?"}{" "}
    <span
      className={cx(
        "todo-item__text",
        todo && todo.completed && "todo-item__text--completed"
      )}
    >
      {todo.content}
    </span>
  </li>
);

// export default Todo;
export default connect(
  null,
  { toggleTodo }
)(Todo);

VisibilityFilters.js

import React from "react";
import cx from "classnames";
import { connect } from "react-redux";
import { setFilter } from "../redux/actions";
import { VISIBILITY_FILTERS } from "../constants";

const VisibilityFilters = ({ activeFilter, setFilter }) => {
  return (
    <div className="visibility-filters">
      {Object.keys(VISIBILITY_FILTERS).map(filterKey => {
        const currentFilter = VISIBILITY_FILTERS[filterKey];
        return (
          <span
            key={`visibility-filter-${currentFilter}`}
            className={cx(
              "filter",
              currentFilter === activeFilter && "filter--active"
            )}
            onClick={() => {
              setFilter(currentFilter);
            }}
          >
            {currentFilter}
          </span>
        );
      })}
    </div>
  );
};

const mapStateToProps = state => {
  return { activeFilter: state.visibilityFilter };
};
// export default VisibilityFilters;
export default connect(
  mapStateToProps,
  { setFilter }
)(VisibilityFilters);

https://github.com/aad61404/ITmarathon2020/tree/master/code-template/09-redux-Todos/src


上一篇
反正我想學09-React-Redux-TodoList(中)
系列文
反正我想學-Web綜合練習紀錄30天11
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言