2015-04-26 41 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

这正是我正在寻找的解释类型。感谢您抽出时间详细说明这一过程,并提出如何重构该简单组件的冗长性。 –

相关问题