iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
Modern Web

React Native & Redux 初步探討系列 第 28

Day 28 加入 Action

第 28 天 !

倒數 3 天!

當我們道路都打通後,我們要開始想要傳什麼資料進去,

首先,我們要確定要放在 redux store 的資料是什麼?

通常,我們會把我們整個專案都會用到的資料放入到 store 裡,

所以,我們先把 todoList 的資料移入到 todoReducer

const initState = {
  list: [],
};

export default function todoReducer(state = initState, action) {
  return state;
}

我們會先設定好 initState ,並且把它當作這個 todoReducer state 的初始值,

最後 return ,這樣我們就把我們的 todoList 保存在 store 裡了

再來我們需要從 mapStateToProps 拿到我們的 todoList

const mapStateToProps = ({ todo }) => {
  return {
    todo,
  };
};

再來導入到 ToDoList Component,

function ToDoList({ todo, changeItemStatus }) {
  const { list } = todo;
  return (
    <FlatList
      data={list}
      renderItem={({ item, index, separators }) => {
        const isEven = index % 2 === 0;
        const isDone = item.status === 'done';
        return (
          <ToDoItem
            isEven={isEven}
            isDone={isDone}
            text={item.text}
            onPress={changeItemStatus}
          />
        );
      }}
      keyExtractor={(item) => item.id}
    />
  );
}

這樣,我們就已經從 store 取出 todoListcomponent

當我們已經取得資料後,我們需要去設定 action ,讓我們可以去操控我們的資料,

action 都是根據需求去設定的,

針對 todoList 需求如下:

  • 新增
  • 修改狀態
  • 全部完成

我們在根目錄建立 actions 資料夾,並在底下建立兩個檔案,

  • types.js
  • creators.js

types 是專門放置 action type , creators 就是放置 action creator

  • types.js
export const INSERT_TODO = 'INSERT_TODO';

export const CHANGE_TODO_STATUS = 'CHANGE_TODO_STATUS';

export const ALL_TODO_COMPLETE = 'ALL_TODO_COMPLETE';

action type , 通常會用全部大寫的方式表示,內容跟變數名稱會是一致的

  • creators.js
import { ALL_TODO_COMPLETE, CHANGE_TODO_STATUS, INSERT_TODO } from './types';

export const insertToDoAction = (payload) => {
  return {
    type: INSERT_TODO,
    payload,
  };
};

export const changeToDoStatusAction = (payload) => {
  return {
    type: CHANGE_TODO_STATUS,
    payload,
  };
};

export const completeAllAction = () => {
  return {
    type: ALL_TODO_COMPLETE,
  };
};

再來,我們到 todoReducer 設定我們的 action 動作,

const initState = {
  list: [],
};

const insertToDo = (state, item) => {
  return {
    ...state,
    list: [...state.list, item],
  };
};

const changeToDoStatus = (state, { id }) => {
  const { list } = state;
  const index = list.findIndex((item) => item.id === id);

  const nowItem = list[index];

  const newStatus = nowItem.status === 'done' ? 'not done' : 'done';

  list[index] = {
    ...nowItem,
    status: newStatus,
  };

  return {
    ...state,
    list: [...list],
  };
};

const allToDoComplete = (state) => {
  return {
    ...state,
    list: state.list.map((item) => {
      return {
        ...item,
        status: 'done',
      };
    }),
  };
};

export default function todoReducer(state = initState, { type, payload }) {
  switch (type) {
    case INSERT_TODO:
      return insertToDo(state, payload);
    case CHANGE_TODO_STATUS:
      return changeToDoStatus(state, payload);
    case ALL_TODO_COMPLETE:
      return allToDoComplete(state);
    default:
      return state;
  }
}

這時候,就把從 App component 的邏輯遷到 todoReducer 裡,

我們移入到 Header component

現在來設定 mapDispatchToProps

假如沒有什麼特別要設定的,

我們可以直接把 action creator 拿來用就好

const mapDispatchToProps = {
  insertToDoAction,
};

Header componentinsertToDoAction 取代 createToDoItem

onAddButtonPress = () => {
  const { inputValue } = this.state;

  const item = {
    id: new Date().getTime(),
    text: inputValue,
    status: 'not done',
  };

  this.setState(() => {
    return {
      inputValue: '',
    };
  });

  this.props.insertToDoAction(item);
};

Complete All ButtoncompleteAllAction 取代 handleCompleteAll

<FeatureButton text={'Complete All'} onPress={this.props.completeAllAction} />

再來到 ToDoList component

  • mapDispatchToProps
const mapDispatchToProps = {
  changeToDoStatusAction,
};
  • ToDoItem component
<ToDoItem
  isEven={isEven}
  isDone={isDone}
  text={item.text}
  onPress={() => changeToDoStatusAction(item.id)}
/>

這樣就大功告成啦


上一篇
Day 27 Redux 接入 component
下一篇
Day 29 middleware - thunk
系列文
React Native & Redux 初步探討33

1 則留言

0
juck30808
iT邦新手 3 級 ‧ 2021-10-14 12:13:25

恭喜即將邁入完賽~/images/emoticon/emoticon08.gif

我要留言

立即登入留言