反应组件状态不更新(FLUX App)

时间:2016-06-27 02:11:23

标签: reactjs reactjs-flux

我正试图建立一个react / flux应用程序,大致如下: https://scotch.io/tutorials/getting-to-know-flux-the-react-js-architecture

我已经完成了大部分工作,但是当我更新状态时,组件不会重新渲染。有人可以帮忙吗?

感谢。 :)

回购是https://github.com/jmsherry/flux_hand

CounterStore.js

import Dispatcher from 'Flux';
import AppDispatcher from './../dispatcher/AppDispatcher';
import CounterConstants from '../constants/constants';
import { EventEmitter } from 'events';
import assign from 'object-assign';


let _count = 5;

function increment() {
  _count +=1;
}

function decrement() {
  _count -=1;
}

let CounterStore = assign({}, EventEmitter.prototype, {

  getCount() {
    return _count;
  },

  emitChange() {
    this.emit(CounterConstants.CHANGE_EVENT);
  },

  /**
   * @param {function} callback
   */
  addChangeListener(callback) {
    this.on(CounterConstants.CHANGE_EVENT, callback);
  },

  /**
   * @param {function} callback
   */
  removeChangeListener(callback) {
    this.removeListener(CounterConstants.CHANGE_EVENT, callback);
  },

  dispatcherIndex: AppDispatcher.register(function(payload) {
    console.log('blah', arguments);
    var action = payload.action;
    var text;

    switch(action.actionType) {
      case CounterConstants.INCREMENT:
          console.log('inc', _count);
          increment();
          console.log(_count);
          CounterStore.emitChange();
        break;

      case CounterConstants.DECREMENT:
      console.log('dec', _count);
        decrement();
        console.log(_count);
        CounterStore.emitChange();
        break;
    }

    return true; // No errors. Needed by promise in Dispatcher.
  })

});

export default CounterStore;

AppDispatcher.js

import { Dispatcher } from 'Flux';

const AppDispatcher = new Dispatcher();

AppDispatcher.handleViewAction = function(action) {
  console.log('in', arguments);
  this.dispatch({
    source: 'VIEW_ACTION',
    action
  });
}

export default AppDispatcher;

constants.js

import keyMirror from 'keymirror';

const CounterConstants = keyMirror({
  INCREMENT: null,
  DECREMENT: null
});

CounterConstants.CHANGE_EVENT = 'change';

export default CounterConstants;

actions.js

import AppDispatcher from '../dispatcher/AppDispatcher';
var CounterConstants = require('../constants/constants');

const CounterActions = {

  /**
   * @param  {string} text
   */
  increment() {
    AppDispatcher.handleViewAction({
      actionType: CounterConstants.INCREMENT
    });
  },

  decrement() {
    AppDispatcher.handleViewAction({
      actionType: TodoConstants.DECREMENT
    });
  }

};

export default CounterActions;

counter.js< - 父视图

import React,{Component} from 'react';
import ReactDOM from 'react-dom';
import CounterConstants from './../constants/constants';
import AppDispatcher from './../Dispatcher/AppDispatcher.js';
import Controls from './Controls';
import Display from './Display';

class Counter extends Component {
  render(){
    return (
      <div className="counter">
        <h1>My counter</h1>
        <Display />
        <Controls />
      </div>
    )
  }
}

export default Counter;

controls.js

import React,{Component} from 'react';
import ReactDOM from 'react-dom';
import CounterConstants from './../constants/constants';
import AppDispatcher from './../dispatcher/AppDispatcher';
import CounterActions from './../actions/actions';

class Controls extends Component {
  render(){
    console.log('here', AppDispatcher);
    return (
      <div className="controls">
        <button onClick={CounterActions.increment}>+</button>
        <button onClick={CounterActions.decrement}>-</button>
      </div>
    )
  }
}

export default Controls;

display.js

import React,{Component} from 'react';
import ReactDOM from 'react-dom';
import CounterConstants from './../constants/constants';
import CounterStore from './../stores/CounterStore';

// Method to retrieve application state from store
function getAppState() {
  console.log('getting app state...');
  return {
    count: CounterStore.getCount()
  };
}

class Display extends Component {
  constructor(props) {
    super(props);
    this.state = getAppState();
  }

  // Update view state when change event is received
  _onChange() {
    console.log('prechange', this.state);
    const newState = getAppState();
    console.log('newState', newState);
    (newState) => this.setState;
  }

  // Listen for changes
  componentDidMount() {
    CounterStore.addChangeListener(this._onChange.bind(this));
  }

  // Unbind change listener
  componentWillUnmount() {
    CounterStore.removeChangeListener(this._onChange.bind(this));
  }

  shouldComponentUpdate( newProps, newState ) {
    console.log('shouldComponentUpdate', arguments);
  }

  render() {
    let count = getAppState().count;
    console.log('rendering', count, this.state);
    return (
      <div className = "display" >
        <p>State: { this.state.count }</p>
        <p>count: { count }</p>
      </div>
    )
  }
}

export default Display;

3 个答案:

答案 0 :(得分:0)

除非我在您的代码中遗漏了某些内容,否则您不会在任何地方调用setState来更新您的状态,这是React更新状态并强制重新渲染的惯用方法。

您的_onChange方法应该使用新状态调用setState,组件将自动重新呈现。

更多阅读:

https://facebook.github.io/react/docs/component-api.html

答案 1 :(得分:0)

因此,您似乎在匿名函数的括号中调用setState,而实际上只需在this方法中使用_onChange调用它。

尝试更改此

(newState) => this.setState;

到此:

this.setState(newState);

编辑:

您可能必须在Display构造函数中包含对此的绑定,如下所示:

  constructor(props) {
    super(props);
    this.state = getAppState();
    this._onChange = this._onChange.bind(this);
  }

答案 2 :(得分:0)

OK!所以,我遇到this绑定问题,所以我使用了es6箭头函数。我是es6的一些新手,我在那里得到的东西是行不通的。这不是你执行箭头功能的方式,这就是为什么它不起作用......