Redux 入門 Demo:TodoList

Ozzie發表於2020-04-03

Demo說明

  1. 本次 Demo 使用了 antd 呈現樣式,需要通過 npm install antd --save 安裝該元件庫
  2. 在使用 Redux 之前,需要安裝 redux,可以用 npm install redux --save 安裝

程式碼以及說明

需熟記的圖

結果樣式

程式碼

  1. 目錄結構

     |-src
       |-index.js
       |-TodoList.js
       |-store
         |-index.js
         |-reducer.js
  2. /src/index.js

     //渲染頁面
    
     import React from 'react'
     import ReactDOM from 'react-dom'
     //引入TodoList元件
     import TodoList from './TodoList'
    
     ReactDOM.render(
       <TodoList />,
       document.getElementById('root')
     )
  3. /src/TodoList.js

     //TodoList元件
    
     import React, { Component } from 'react'
     //引入store
     import store from './store/index'
     //引入antd樣式
     import 'antd/dist/antd.css'
     //按需引入輸入框、按鈕、列表項樣式
     import { Input, Button, List } from 'antd'
    
     class TodoList extends Component {
       constructor(props) {
         super(props);
         //通過store的getState方法獲取公共資料
         this.state = store.getState();
         this.handleInputChange = this.handleInputChange.bind(this);
         this.handleStoreChange = this.handleStoreChange.bind(this);
         this.handleBtnClick = this.handleBtnClick.bind(this);
         //只要store發生改變,就立即執行handleStoreChange這個方法
         store.subscribe(this.handleStoreChange);
       }
    
       render() {
         return (
           <div style={{marginLeft:'30px', marginTop:'10px'}}>
             <div>
               <Input placeholder='TodoList'
                      style={{width:'300px', marginRight:'10px'}}
                      value={this.state.inputValue}
                      onChange={this.handleInputChange}
               />
               <Button type='primary'
                       onClick={this.handleBtnClick}
               >
                 提交
               </Button>
             </div>
             <List bordered
                   style={{marginTop:'10px', width:'500px'}}
                   dataSource={this.state.list}
                   renderItem={
                     item => ( <List.Item>{item}</List.Item> )
                   }
             />
           </div>
         )
       }
    
       handleInputChange(e) {  //觸發功能:改變輸入框值
         const action = {  //將此需求用action表達
           type: 'changeInputValue',  //type即需求的描述,
           value: e.target.value  //value是要傳給sotre的值
         };
         store.dispatch(action);  //將action傳給store,store會自動將action物件的內容傳給reducer
       };
    
       handleStoreChange() {  //得到新的state值
         //用getState方法得到最新的store資料,並通知setState更新
         this.setState(store.getState())
       };
    
       handleBtnClick() {  //觸發功能:增加列表項
         const action = {
           type: 'addTodoItem'
         };
         store.dispatch(action)  //傳給Store
       }
     }
    
     export default TodoList;
  4. /src/store/index.js

     //Store部分
    
     //從redux中引入createStore方法
     import { createStore } from 'redux';
     //引入Reducer
     import reducer from './reducer';
    
     const store = createStore(  //通過createStore()建立一個公共的資料儲存倉
       reducer,  // 將reducer部分傳遞給store
     );
    
     export default store;
  5. /src/store/reducer.js

     //Reducer部分
    
     const defaultState = {
       inputValue: '',
       list: [1, 2, 3]
     };
    
     //reducer負責管理整個store中的資料
     //reducer裡面必須返回一個函式,引數中的state就是整個store倉庫裡儲存的資料
     export default (state = defaultState, action) =>  {  //state先定為defaultState
       if(action.type === 'changeInputValue') {  //若需觸發改變輸入框值的功能
         //深拷貝state
         const newState = JSON.parse(JSON.stringify(state));
         //改變state的輸入框值,即是改變渲染的輸入框值
         newState.inputValue = action.value;
         //由於reducer不能直接修改傳遞過來的state,所以通過newState返回修改的結果
         // store會根據newState替換原來的state值
         return newState;
       }
       if(action.type === 'addTodoItem') {  //若需觸發增加列表項的功能
         const newState = JSON.parse(JSON.stringify(state));  //深拷貝state
         newState.list.push(newState.inputValue);  //新增列表項
         newState.inputValue = '';  //清空輸入欄
         return newState;
       }
       return state;
     }
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章