如何在ReactJS中处理Store的监听?

时间:2016-01-18 15:51:13

标签: reactjs flux

以下是平均商店:

// StoreUser
import EventEmitter from 'eventemitter3';
import Dispatcher from '../dispatcher/dispatcher';
import Constants from '../constants/constants';
import React from 'react/addons';
import serverAddress from '../utils/serverAddress';
import socket from './socket';

var CHANGE_EVENT = "change";
var storedData = {
  userName: null
}

socket
  .on('newUserName', (newUserName)=>{
    storedData.userName = newUserName;
    AppStore.emitChange();
  })


function _changeUserName (newUserName) {
  socket.emit('signUp', newUserName)
}

var AppStore = React.addons.update(EventEmitter.prototype, {$merge: {

  emitChange(){
    // console.log('emitChange')
    this.emit(CHANGE_EVENT);
  },

  addChangeListener(callback){
    this.on(CHANGE_EVENT, callback)
  },

  removeChangeListener(callback){
    this.removeListener(CHANGE_EVENT, callback)
  },

  getStoredData(callback) { 
    callback(storedData);
  },

  dispatcherIndex:Dispatcher.register(function(payload){
    var action = payload.action;
    switch(action.actionType){
      case Constants.CHANGE_USER_NAME:
        _changeUserName(payload.action.actionArgument);
        break;
    }
    return true;
  })
}});

export default AppStore;

这是连接到商店的平均组件:

import React from 'react';

import StoreUser from '../../stores/StoreUser';

import Actions from '../../actions/Actions';

export default class User extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      userName: null,
    };
  }

  componentDidMount() {
    StoreUser.addChangeListener(this._onChange.bind(this));
  }

  componentWillUnmount() {
    StoreUser.removeChangeListener();
  }

  render() {
    const { userName } = this.state;
    return (
      <div key={userName}>
        {userName}
      </div>
    );
  }
  _onChange(){
    StoreUser.getStoredData(_callbackFunction.bind(this))
    function _callbackFunction (storedData) {
      // console.log('storedData', storedData)
      this.setState({
        userName: storedData.userName,
      })
    }
  }

}

这个工作非常好。但是现在,我在这种方法中面临着很大的错误: 例如,WebApp具有用户名称的侧边栏,该名称正在侦听StoreUser以显示最新的userName。此外,webapp还有一个组件(页面),其中包含用户的配置文件(包括userName),它也在监听StoreUser。如果我将卸载此组件,则侧栏将停止监听StoreUser。

我从egghead.io或其他一些教程中学到了这种方法 - 我不记得,到底在哪里。似乎,我错过了一些关于如何管理商店听众的重要观点。您能否提出简单的方法来解决上述问题?

我试图坚持最初的Flux架构,请不要告诉我任何Flux架构的替代实现。这是我唯一的问题。

1 个答案:

答案 0 :(得分:1)

问题是卸载时你不能删除你的监听器。你必须非常小心地删除你添加的完全相同的函数引用(传递this.callback.bind(this)两次不起作用,因为这两个调用返回不同的函数引用)。最简单的方法是:

&#13;
&#13;
//...
export default class User extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      userName: null,
    };
    // create fixed bound function reference we can add and remove
    // (like the auto-binding React.createComponent does for you).
    this._onChange = this._onChange.bind(this);
  }

  componentDidMount() {
    StoreUser.addChangeListener(this._onChange);
  }

  componentWillUnmount() {
    // make sure you remove your listener!
    StoreUser.removeChangeListener(this._onChange);
  }
//...
&#13;
&#13;
&#13;

您的代码有几个奇怪之处:<​​/ p>

  • 为什么StoreUser.getStoredData会进行回调,而不仅仅是返回数据?使用flux,您应该始终同步查询。如果数据需要提取,则getter可以触发ajax提取,返回null,然后在ajax请求返回时触发另一个操作,从而导致另一个emitChange,从而最终触发使用用户数据重新呈现。
  • 看起来您的商店正在触发服务器写入。通常情况下,这将是一个行动创造者而不是商店的责任,虽然我不认为这是商店的主要违规行为。