2015-04-26 63 views
1

我目前有一個非常簡單的React應用程序,它使用狀態來確定幾個視圖。點擊submit元素可以簡單地調用一個傳遞登錄或註冊憑證的端點。我可以沿着這條路繼續使用從服務器返回的React和JSON來確定我的視圖,但我知道這不是處理數據的方式。瞭解如何使用Flummox實現Flux體系結構

我的問題是,從這裏,我該如何使用Flummox實現Flux模式?我是否會對有效載荷進行操作並在操作或商店中進行API調用?我試圖理解從UI中的動作到我的API調用,以便獲取響應和UI對商店中的更改做出響應的正確方法。

以下是我的Auth組件的代碼。我想看一個如何在這種簡單的情況下使用Flummox的例子,所以我可以理解需要擴展和添加功能。

Auth.jsx

'use strict'; 

var React = require('react'); 
var request = require('request'); 

var Auth = React.createClass({ 

    getInitialState: function() { 
    return { 
     name: '', 
     email: '', 
     pass: '', 
     passConfirm: '', 
     login: true, 
     register: false 
    }; 
    }, 

    handleLogin: function(){ 
    this.setState({ 
     login: true, 
     register: false 
    }); 
    }, 

    handleRegister: function(){ 
    this.setState({ 
     register: true, 
     login: false 
    }); 
    }, 

    handleName: function(event){ 
    this.setState({ 
     name: event.target.value 
    }); 
    }, 

    handleEmail: function(event){ 
    this.setState({ 
     email: event.target.value 
    }); 
    }, 

    handlePass: function(event){ 
    this.setState({ 
     pass: event.target.value 
    }); 
    }, 

    handlePassConfirm: function(event){ 
    this.setState({ 
     passConfirm: event.target.value 
    }); 
    }, 

    handleSubmit: function(){ 

    var register = { 
     name: this.state.name, 
     email: this.state.email, 
     password: this.state.pass, 
     confirmPassword: this.state.passConfirm 
    }; 

    var endpoint = 'http://localhost:3000'; 

    request({ 
     uri: endpoint + '/register', 
     method: 'POST', 
     json: register 
    }, function(error, response, body){ 
     if (error) { 
     console.log(error); 
     } else { 
     console.log(response); 
     } 
    }); 
    }, 

    renderLogin: function() { 
    return (
     <form className="login"> 
     <div className="input-container"> 
      <input type='text' value={this.state.email} onChange={this.handleEmail} placeholder="email" /> 
      <input type='password' value={this.state.password} onChange={this.handlePass} placeholder="password" /> 
     </div> 

     <div className="auth-submit" onClick={this.handleSubmit}>Login</div> 
     </form> 
    ); 
    }, 

    renderRegister: function(){ 

    return (
     <form className="register"> 
     <div className="input-container"> 
      <input type='text' value={this.state.name} onChange={this.handleName} placeholder="name" /> 
      <input type='email' value={this.state.email} onChange={this.handleEmail} placeholder="email" /> 
      <input type='password' value={this.state.pass} onChange={this.handlePass} placeholder="password" /> 
      <input type='password' value={this.state.passConfirm} onChange={this.handlePassConfirm} placeholder="confirm password" /> 
     </div> 

     <div className="auth-submit" onClick={this.handleSubmit}>Register</div> 
     </form> 
    ); 
    }, 

    render: function(){ 

    var auth = null; 
    if (this.state.login) { 
     auth = this.renderLogin(); 
    } else if (this.state.register) { 
     auth = this.renderRegister(); 
    } 

    return (
     <div className="auth-container"> 
     <div className="auth-logo">Flow</div> 
     {auth} 
     <div className="auth-select"> 
      <div className="auth-label-container"> 
      <div className="auth-label" onClick={this.handleLogin}>Login</div> 
      </div> 
      <div className="auth-label-container"> 
      <div className="auth-label" onClick={this.handleRegister}>Register</div> 
      </div> 
     </div> 
     </div> 
    ); 
    }, 
}); 

module.exports = Auth; 

回答

12

潛入流量之前,我建議清理你現有的反應代碼。

作爲一個開始,我會盡量減少元件本身的狀態。例如,您可以使用單個screen作爲狀態,而不是單獨爲loginregister指定狀態,該狀態接受您渲染的實際屏幕/視圖(登錄/註冊)的字符串值。

同樣,每個renderLogin()renderRegister()作爲自己的組件更好。因此,您的Auth組件最終將成爲控制器視圖。

表單處理看起來過於冗長:您已經爲每個單獨的字段定義了單獨的處理程序,但只需一個handleChange()即可(您可以在輸入元素中設置name="<state-field-name>"以引用所引用的狀態字段)。


AFER,你就可以開始構建用驚訝和感動您的應用程序的狀態(而不是局部組件的狀態),進入商店的流量模式。

我假設你有read the docs,但作爲一個總結驚訝提供StoreAction助手建模應用程序的數據(真理的來源)和UI操作。

的動作模塊可看起來像這樣:

import { Actions } from 'flummox'; 


export default class AuthActions extends Actions { 

    gotoScreen(screenName) { 
    return screenName; 
    } 

    register(requestBody) { 
    // Here you deal with your authentication API, 
    // make async requests and return a promise. 
    // This part is specific to your backend. 
    return AuthAPI.register(requestBody) 
        .then(
        (value) => Promise.resolve(value), 
        (reason) => Promise.reject(reason) 
       ); 
    } 

} 

而一個AuthStore將是真理的來源,即處理實際應用狀態。這注冊了操作,所以每當操作發出更改時,它都知道如何更新自己。

import { Store } from 'flummox'; 


export default class AuthStore extends Store { 

    constructor(flux) { 
    super(); 

    let authActions = flux.getActions('auth'); 

    // Here you register the functions which will take care 
    // of handling the actions and update the store's state. 
    // These can be sync or async. 
    this.register(authActions.gotoScreen, this.handleGotoScreen); 
    this.registerAsync(authActions.register, this.handleRegisterBegin, 
              this.handleRegisterSuccess, 
              this.handleRegisterError); 

    // This is the initial state of your flux store 
    this.state = { 
     screen: 'login', 
     // ... any extra state your app might need 
    }; 
    } 


    /* Screen handling */ 

    handleGotoScreen(screenName) { 
    this.setState({screen: screenName}); 
    } 

    /* Register */ 

    handleRegisterBegin(requestBody) { 
    this.setState({ 
     // change state based on action 
    }); 
    } 

    handleRegisterSuccess() { 
    this.setState({ 
     // change state based on action 
    }); 
    } 

    handleRegisterError(errors) { 
    this.setState({ 
     // change state based on action 
    }); 
    } 

} 

這些需要封裝在Flux對象中,然後可以在應用程序的任何位置引用它。

import { Flummox } from 'flummox'; 

import AuthActions from './AuthActions'; 
import AuthStore from './AuthStore'; 


export default class Flux extends Flummox { 

    constructor() { 
    super(); 

    this.createActions('auth', AuthActions); 
    this.createStore('auth', AuthStore, this); 
    } 

} 

但是,您的意見如何瞭解商店的狀態?用preferred way來粘貼你的商店的意見是通過使用FluxComponent,這將通過使用FluxComponent時通過道具收到商店的狀態。

FluxComponent收到您的應用程序的Flux對象的實例,並且還需要指定要連接到哪個存儲。

import Flux from './Flux'; 
let flux = new Flux(); 

<FluxComponent flux={flux} connectToStores={['auth']}> 
    <Auth /> 
</FluxComponent> 

該狀態作爲道具傳遞,您可以直接引用值,就像正常使用道具一樣。

與此同時,這允許訪問底層的意見flux道具,這讓我們獲得的動作,因此能夠在用戶交互發生在觸發它們:

// You can fire actions from anywhere in your component 
this.props.flux.getActions('auth').gotoScreen('register') 

有了這個結束(或開始)通量循環。

+0

這正是我正在尋找的解釋類型。感謝您抽出時間詳細說明這一過程,並提出如何重構該簡單組件的冗長性。 –

相關問題