React + Antd + Redux改進以前簡單的todolist

前段時間實現了React + Antd實現簡單的todolist,組件之間的傳值經過props層層傳遞太過繁瑣,此次改進了項目引入了redux進行狀態的管理。項目地址react

1. 安裝配置Redux

  • 安裝redux
yarn add redux
複製代碼
  • 配置redux,在根目錄下新建文件夾store,在store新建index.js,引入redux的createStore建立簡單的store
import { createStore } from "redux";

const reducer = function(state = [], action) {
  return state;
}

const store = createStore(reducer);
複製代碼

2. 組織Redux代碼

  1. 新建store的目錄結構以下所示

2. contants/index.js文件用來定義咱們接下來的行爲

export const ADD_TODO = 'add_todo' // 增
export const DELETE_TODO = 'delete_todo' // 刪
export const COMPLETE_TODO = 'complete_todo' // 改
export const SEARCH_TODO = 'search_todo'  // 查
複製代碼
  1. actions/index.js用來定義Action,Action 是把數據從應用傳到 store 的有效載荷。它是 store 數據的惟一來源。通常來講你會經過 store.dispatch() 將 action 傳到 store。這裏使用Action建立函數來生成action
import {ADD_TODO, DELETE_TODO, COMPLETE_TODO, SEARCH_TODO} from '../constants'

export function addTodo (todo) {
  return {
    type: ADD_TODO,
    todo
  }
}

export function deleteTodo (id) {
  return {
    type: DELETE_TODO,
    id
  }
}

export function completeTodo (id) {
  return {
    type: COMPLETE_TODO,
    id
  }
}

export function searchTodo (text) {
  return {
    type: SEARCH_TODO,
    text
  }
}
複製代碼
  1. reducers/index.js定義reducer,reducer 就是一個純函數,接收舊的 state 和 action,返回新的 state。指定了應用狀態的變化如何響應 actions 併發送到 store 。
import {ADD_TODO, DELETE_TODO, COMPLETE_TODO, SEARCH_TODO} from '../constants'

let initState = [
  {
    id: 1,
    text: 'test123',
    completed: true
  },
  {
    id: 2,
    text: 'testabc',
    completed: false
  },
  {
    id: 3,
    text: 'done123',
    completed: true
  }
]

const todoReducer = (state = initState, action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.todo]
    case DELETE_TODO: 
      return state.filter(item => {
        return item.id !== action.id
      })
    case COMPLETE_TODO:
      return state.map(item => {
        let obj = action.id === item.id ? {...item, completed: !item.completed} : item
        return obj
      })
    case SEARCH_TODO:
      if (action.text === '') {
        return state
      } else {
        return state.filter(item => {
          return item.content.indexOf(action.text) !== -1
        })
      }
    default:  
      return state
  }
}

export default todoReducer
複製代碼
  1. 最後修改store/index.js
import {createStore} from 'redux'
import todoReducer from './reducers'

const store = createStore(todoReducer)

export default store
複製代碼

補充:若是有多個reducer,能夠這樣處理git

import { combineReducers } from 'redux';
import reducer1 from './reducers/reducer1'
import reducer2 from './reducers/reducer2'

const allReducers = {
  reducer1,
  reducer2
}

const rootReducer = combineReducers(allReducers);

let store = createStore(rootReducer);
複製代碼

4. 安裝調試工具

  • 在Chrome中安裝redux-devtools-extension插件
  • 在終端安裝redux-devtools-extension
yarn add redux-devtools-extension
複製代碼
  • 安裝完成後修改store/index.js
import {createStore} from 'redux'
import todoReducer from './reducers'
import {composeWithDevTools } from 'redux-devtools-extension'

const store = createStore(todoReducer, composeWithDevTools())

export default store
複製代碼

5. 測試redux

  • 修改App.js,引入redux進行測試,store.subscribe註冊事件監聽當store.dispatch時能夠經過store.getState()顯示出當前的state
import React from 'react';
import TodoList from './TodoList'
import store from './store'
import {addTodo} from './store/actions'

store.subscribe(() => {
  console.log(store.getState())
})

store.dispatch(addTodo({id:4, text: 'nihao', completed: false}))

function App() {
  return (
    <div className="App">
      <TodoList></TodoList>
    </div>
  );
}

export default App;

複製代碼
  • 控制檯打印結果以下,能夠看到新添加的todo

  • 在redux-devtools插件中也能夠觀察到狀態變化

6. 集成react

  1. 安裝react-redux
yarn add react-redux
複製代碼
  1. 修改app.js,使用Provider類將React應用程序包裝在Redux容器中
import React, { Component } from 'react'
import TodoListApp from './components/TodoListApp'
import {Provider} from 'react-redux'
import store from './store'

class App extends Component {
  render () {
    return(
    <Provider store={store}>
      <TodoListApp/>
    </Provider>     
    )
  }
}

export default App
複製代碼

7. 修改項目結構

  • 容器組件和展現組件
    • 容器組件負責與Store交互自身不會觸發action,它向展現組件傳遞由Store得到的props,向Store派發用戶操做展現組件引發的action。
    • 展現組件專一於渲染視圖是無狀態組件,全部數據源於props,通常表示爲函數式組件。
  1. 修改項目結構以下所示

containers文件夾存放容器組件,components文件夾存放展現組件,展現組件由function建立無狀態組件。

  1. 修改todoItem
  • components/TodoItem.js,此時的TodoItem只是負責展現做用沒定義state,數據所有由props傳入
import React from 'react';
import { Typography, Button } from 'antd';
import './TodoItem.less'

const { Text } = Typography;

function TodoItem ({completed, id, content, handleChangeItem,handleDeleteItem}) {
  return (
    <div className="item-container" onDoubleClick={() => handleChangeItem(id)} style={{cursor: 'pointer'}}>
      <Text delete={completed}>{content}</Text>
      <Button type="primary" icon="delete" onClick={() => handleDeleteItem(id)}></Button>
    </div>
  )
}

export default TodoItem;
複製代碼
  • containers/TodoItems,向展現組件中傳入數據
import {connect} from 'react-redux'
import TodoItemComponent from '../components/TodoItem'
import {completeTodo, deleteTodo} from '../store/actions'

const mapDispatchToProps = dispatch => {
  return {
    handleChangeItem: id => {
      dispatch(completeTodo(id))
    },
    handleDeleteItem: id => {
      dispatch(deleteTodo(id))
    }
  }
}
const TodoItemContainer = connect(null, mapDispatchToProps)(TodoItemComponent)

export default TodoItemContainer
複製代碼
  1. 修改DataList
  • 展現組件components/DataList
import React from 'react';
import TodoItem from '../containers/TodoItem'
import { List } from 'antd';

function DataList ({list}) {
  return (
    <List
      bordered
      dataSource={list}
      renderItem={item => (
          <List.Item>
            <TodoItem {...item}/>
          </List.Item>
      )}
    />
  )
}

export default DataList;
複製代碼
  • 容器組件containers/Datalist
import {connect} from 'react-redux'
import TodoListComponent from '../components/DataList'

const mapStateToProps = state => {
  return {
    list: state
  }
}

const TodoListContainer = connect(mapStateToProps)(TodoListComponent)

export default TodoListContainer
複製代碼
  1. 其餘組件也按照上面展現組件和容器組件進行拆分詳情查看項目github

  2. 修改App.js,引入react-redux,被Provider包裹的組件都能拿到storeredux

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

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

export default App;

複製代碼

相關連接:React + Antd實現簡單的todolistbash

React + Antd + Mobx改進以前簡單的todolistantd

相關文章
相關標籤/搜索