React 實踐項目 (二)

来源:http://www.cnblogs.com/yuicon/archive/2017/07/09/7141050.html
-Advertisement-
Play Games

React在Github上已經有接近70000的 star 數了,是目前最熱門的前端框架。而我學習React也有一段時間了,現在就開始用 React+Redux 進行實戰! React 實踐項目 (一)本次實踐代碼 部署好的網址 上回說到用React寫了一個帶Header的首頁,我們這次實踐就使用R ...


React在Github上已經有接近70000的 star 數了,是目前最熱門的前端框架。而我學習React也有一段時間了,現在就開始用 React+Redux 進行實戰!

React 實踐項目 (一)

本次實踐代碼

部署好的網址

上回說到用React寫了一個帶Header的首頁,我們這次實踐就使用Redux進行狀態管理

index

Rudex

應用中所有的 state 都以一個對象樹的形式儲存在一個單一的 store 中。
惟一改變 state 的辦法是觸發 action,一個描述發生什麼的對象。
為了描述 action 如何改變 state 樹,你需要編寫 reducers。

我們接下來開始開始進行登陸與註冊的狀態管理

首先在 src 目錄下創建 redux 文件夾,目錄如下

digag
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   └── favicon.ico
│   └── index.html
│   └── manifest.json
└── src
    └── components
        └── Index
            └── Header.js
            └── LoginDialog.js
            └── RegisterDialog.js
    └── containers
        └── App
            └── App.js
            └── App.css
    └── redux
        └── action
            └── users.js
        └── reducer
            └── auth.js
            └── users.js
        └── sagas
            └── api.js
            └── sagas.js
            └── selectors.js.js
            └── users.js
        └── store
            └── store.js
    └── App.test.js
    └── index.css
    └── index.js
    └── logo.svg
    └── registerServiceWorker.js

代碼可從此獲取

記得在 package.json 中更新依賴

接下來我會開始解釋關鍵代碼

  • action
    action/users.js
/*
 * action 類型
 */
export const REGISTER_USER = 'REGISTER_USER';
// 省略其他action 類型

/*
 * action 創建函數
 */
export const registerAction = (newUser) => {
  return{
    type:REGISTER_USER,
    data: newUser,
  }
};
// 省略其他 action 創建函數
  • reducer
    reducer/users.js
//Immutable Data 就是一旦創建,就不能再被更改的數據。
//對 Immutable 對象的任何修改或添加刪除操作都會返回一個新的 Immutable 對象。
import Immutable from 'immutable';
//從 action 導入需要的 action 類型
import {REGISTER_USER, REGISTER_USER_SUCCESS, REGISTER_USER_FAILURE} from '../action/users';

// 初始化狀態
const initialState = Immutable.fromJS({
  newUser: null,
  error: null,
  saveSuccess: false,
});

//  reducer 就是一個純函數,接收舊的 state 和 action,返回新的 state。
export const users = (state = initialState, action = {}) => {
  switch (action.type) { // 判斷 action 類型
    case REGISTER_USER:  
      return state.merge({   // 更新狀態
        'newUser': action.data,
        'saveSuccess': false,
        'error': null,
      });
    case REGISTER_USER_SUCCESS:
      return state.set('saveSuccess', action.data);
    case REGISTER_USER_FAILURE:
      return state.set('error', action.data);
    default:
      return state
  }
};
  • store
    store/store.js
import {createStore, combineReducers, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga'
import * as reducer from '../reducer/users';

import rootSaga from '../sagas/sagas';

const sagaMiddleware = createSagaMiddleware();

const store = createStore(
  combineReducers(reducer),
  applyMiddleware(sagaMiddleware)
);

sagaMiddleware.run(rootSaga);

export default store;

然後在入口文件使用 store

src/index.js

import {Provider} from 'react-redux';
import store from './redux/store/store';
// 省略其他

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>, document.getElementById('root')
);

在 App.js 中獲取 action 和 狀態

import {registerAction, loginAction} from '../../redux/action/users';
import {connect} from "react-redux";
import {bindActionCreators} from "redux";
 //省略其他

class App extends Component {

  render(){
    return(
      <div className="App">
        //省略
      </div>
    )
  }

}

export default connect(
  (state) => {
// 獲取狀態   state.users  是指 reducer/users.js 文件中導出的 users
// 可以 `console.log(state);` 查看狀態樹
  return { users: state.users }
},
  (dispatch) => {
  return {
// 創建action
    registerActions: bindActionCreators(registerAction, dispatch),
    loginActions: bindActionCreators(loginAction, dispatch),
  }
})(App);
// 在App 組件的props里就有 this.props.users  this.props.registerActions this.props.loginActions 了
// 需要註意的是這裡this.props.users是Immutable 對象,取值需要用this.props.users.get('newUser') 
// 也可在 reducer 里改用 js 普通對象

裝飾器版本:
需要在Babel中開啟裝飾器
裝飾器插件babel-plugin-transform-decorators-legacy

@connect(
  (state) => {
    console.log(state);
    return ({
      users: state.users,
    });
  },
  {registerActions: registerAction, loginActions: loginAction}
)

最後把 registerActions 傳給RegisterDialog子組件,

src/components/Index/RegisterDialog.js

// 省略其他代碼
 handleSubmit = (e) => {
    e.preventDefault();
    // 驗證表單數據
    this.refs.user.validate((valid) => {
      if (valid) {
        // this.state.user 為表單收集的 用戶註冊數據
        this.props.registerActions(this.state.user);
        this.setState({loading: true});
      }
    });
  };

流程是:

  • 調用 action
    this.props.registerActions(this.state.user);
    返回action 為
{
    type:REGISTER_USER,
    data: this.state.user,
}
  • reducer 根據action類型更新狀態
switch (action.type) {
    case REGISTER_USER:
      return state.merge({
        'newUser': action.data,
        'saveSuccess': false,
        'error': null,
      });
//省略其他代碼

這時我們的store里的狀態 newUser就被更新為 註冊彈窗里收集的數據
到這裡都還是同步的action,而註冊是一個非同步的操作。
下篇文章會介紹如何使用 redux-saga 進行非同步操作。
redux-saga 已經在使用了,有興趣的可以自行查看代碼理解。

記得點star:)
項目代碼地址:https://github.com/DigAg/digag-pc-react
vue2版項目代碼地址:https://github.com/DigAg/digag-pc-vue2
相應後端項目代碼地址:https://github.com/DigAg/digag-server


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這是我的第一遍博文,我來試試感覺 ...
  • 1.正則表達式 js 中判斷某個元素是否存在於某個 js 數組中,相當於 PHP 語言中的 in_array 函數。 Array.prototype.in_array=function(e){ var r=new RegExp(','+e+','); return (r.test(','+this. ...
  • 1.xhtml和html有什麼區別 HTML是一種基本的WEB網頁設計語言,XHTML是一個基於XML的置標語言 最主要的不同: XHTML 元素必須被正確地嵌套。 XHTML 元素必須被關閉。 標簽名必須用小寫字母。 XHTML 文檔必須擁有根元素 2、簡述一下src與href的區別: href ...
  • 如果你是一個人在自學前端開發,或者是對前端開發有比較濃厚的興趣正想踏入前端領域,只要你在前端自學路上遇到了自己無法解決的技術難題,那麼儘管將你的疑惑交給我的小伙伴兒們吧,我們都是一群在前端自學路上摸爬滾打的有志青年,希望你可以來和我們共同交流。同時也希望你能獻出自己的一份力,幫助我的小伙伴兒們解決他 ...
  • 上一篇的gulp配置很簡單,主要就是為了demo的查看和調試,這一篇則會相對詳細一些,包括壓縮合併打時間戳等。 在互聯網環境比較好的城市,需要多人協作的,大一點的項目應該都用上了模塊化(這裡主要指commonjs和ES6模塊系統,不是再早的require.js和sea.js)。代碼也會更註重如何分離 ...
  • 摘要: 前端框架 Bootstrap 的模態對話框,可以使用 remote 選項指定一個 URL,這樣對話框在第一次彈出的時候就會自動從這個地址載入數據到 .modal-body 中,但是它只會載入一次,不過通過在事件中調用 removeData() 方法可以解決這個問題。 1. Bootstrap ...
  • 1、對於string,number等基礎類型,==和 是有區別的 1)不同類型間比較,==之比較“轉化成同一類型後的值”看“值”是否相等, 如果類型不同,其結果就是不等 2)同類型比較,直接進行“值”比較,兩者結果一樣 2、對於Array,Object等高級類型,==和 是沒有區別的 進行“指針地址 ...
  • 上次分享完該系列文章後有朋友也建議說1.x版本除了維護也沒有必要學習,可以學習2.0開始學習,我也知道1.x無論是從性能還是架構上都沒有2.x好,但是我想因為現在也有一些朋友還在用1.x版本,因為1.x升級到2.x難度很大,甚至可以說重構,就向我們公司現在還在用1.x版本,所以我還是決定把這系列寫完 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...