2015-06-05 2 views
1

У меня проблема с Flux, которая меня убила. Я вызываю действие при загрузке страницы, но по какой-то причине он не обновляет состояние в компоненте. В этом примере у меня есть this.props.count, установленный в 5 (по умолчанию в TestStore). Затем я вызываю действие, чтобы увеличить его в componentDidmount до 6, но он не обновляет состояние компонента. Он остается на 5. Затем, если я нажму ссылку, чтобы вручную обновить его, он будет от 5 до 7.Flux action не обновляет состояние, я делаю это неправильно?

Я думаю, что это как-то связано с тем, что Flux changeListener добавляется к компоненту верхнего уровня после того, как действие посланы?

Если я установил changeListener в componentWillMount вместо componentDidMount в компонент верхнего уровня, тогда все будет работать. Но это не похоже на правильный путь? Я чувствую, что что-то упускаю.

Вот console.log и компоненты ...

console.log

< тестер />

import React from 'react'; 
import TestActions from '../actions/TestActions'; 

export default class Tester extends React.Component { 

    componentDidMount() { 
    // this.props.count defaults to 5 
    // This brings it to 6 
    TestActions.increaseCount(); 
    } 

    render() { 
    return (
     <div> 
     // Count should display 6, but shows 5 
     Count: {this.props.count} 
     <br /> 
     <a href="#" onClick={this._handleClick}>Increase</a> 
     </div> 
    ); 
    } 

    _handleClick(e) { 
    e.preventDefault(); 
    TestActions.increaseCount(); 
    } 

} 

< Применение />

import React from 'react'; 
import {RouteHandler} from 'react-router'; 
import TestStore from '../stores/TestStore'; 

export default class Application extends React.Component { 

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

    getStateFromStores() { 
    return { 
     count: TestStore.getCount() 
    }; 
    } 

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

    _onChange() { 
    this.setState(this.getStateFromStores()); 
    } 

    componentWillUnmount() { 
    TestStore.removeChangeListener(this._onChange); 
    } 

    render() { 
    return (
     <RouteHandler {...this.state} {...this.props}/> 
    ); 
    } 

} 

TestStore

var AppDispatcher = require('../dispatchers/AppDispatcher'); 
var EventEmitter = require('events').EventEmitter; 
var TestConstants = require('../constants/TestConstants'); 
var assign = require('object-assign'); 

var CHANGE_EVENT = 'change'; 

var _count = 5; 

function increaseCount() { 
    _count = _count + 1; 
} 

var TestStore = assign({}, EventEmitter.prototype, { 

    getCount: function() { 
    return _count; 
    }, 

    emitChange: function() { 
    console.log('TestStore.emitChange'); 
    this.emit(CHANGE_EVENT); 
    }, 

    addChangeListener: function(callback) { 
    console.log('TestStore.addChangeListener'); 
    this.on(CHANGE_EVENT, callback); 
    }, 

    removeChangeListener: function(callback) { 
    this.removeListener(CHANGE_EVENT, callback); 
    } 
}); 

AppDispatcher.register(function(action) { 
    var text; 

    switch(action.actionType) { 
    case TestConstants.INCREASE_COUNT: 
     increaseCount(); 
     TestStore.emitChange(); 
     break; 

    default: 
     // no op 
    } 
}); 

module.exports = TestStore; 

ответ

0

Как вы сказали, этот вопрос находится в <Application />: Вы начинаете слушать магазин в componentDidMount, в то время как вы должны сделать это в componentWillMount, в противном случае вы начнете слушать изменения после того, как все компоненты поэтому вы теряете начальное приращение.

componentWillMount() { 
    TestStore.addChangeListener(this._onChange); 
    } 

Во всяком случае, я хотел бы предложить, чтобы выполнить действие в верхнем компоненте:

В <Application />

componentDidMount() { 
    TestActions.increaseCount(); 
}, 

_handleClick() { 
    TestActions.increaseCount(); 
}, 

render() { 
    return <Tester callback={this._handleClick} count={this.state.count} /> 
} 

В <Tester/>

<a href="#" onClick={this.props.callback}>Increase</a> 
+0

я вижу. Я увидел, что это устранило проблему, когда я изменил ее на 'componentWillMount'. Но я не знал, было ли это решение или нет. Просто потому, что каждый учебник, который я прочитал, имел changeListeners в 'componentDidMount' ... Я не знал, была ли причина для этого или нет :) Я думал, возможно, был способ запустить действие после того, как все родительские компоненты установлен. – TylerW

+0

Ну, может быть, более правильно использовать componentDidMount. В вашем случае я бы реорганизовал архитектуру, имея верхний компонент, выполняющий действия, и дочерний компонент, используя обратные вызовы отцу. – gcedo

+0

Не возражаете ли вы дать небольшой пример? Я немного newb :) – TylerW

Смежные вопросы