为什么我的应用程序状态更新没有来自store-flux的更改事件

时间:2017-12-28 00:53:53

标签: reactjs state flux

TL; DR
这是我的一个视频,解释了(很差)这个问题:
https://www.youtube.com/watch?v=lJogEfYYHRo&feature=youtu.be

我正在使用flux在Web应用程序上创建聊天功能。 我有一个名为messages的数组商店。正如预期的那样,只要存储发生变化,商店就会发出更改事件,并且视图上的监听器会听到它并使用商店中的getter方法更新状态。

在这个应用程序中,我想加载一些初始消息(模仿从数据库中获取消息的历史记录)。但是,出于某种原因,每当我将视图上的状态设置为store getter(返回消息数组)时,只要将新消息推送到商店中的messages数组,它就会继续更新,这不应该是。它应该仅在广播变更事件时更新。为什么会这样?

这里的查看&所有相关代码

class ChatBar extends React.Component {

constructor(props) {
    super(props);
    // CHAT FUNCTIONS
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this._onChange = this._onChange.bind(this);

    this.state = {
        chat__messages: [],
        chat__playercount: 0,
        chat__message_input: "",
    };
}

// ====================================================

componentDidMount(){
    ChatStore.on(CHANGE, this._onChange);
    ChatStore.init();    
}

componentWillUnmount() {
    ChatStore.removeListener(CHANGE);
}

_onChange() {
    // IN THE FUTURE NEED TO CHANGE THIS TO 
    // RETURN ENTIRE STATE, NOT JUST MESSAGES
    this.setState({chat__messages: ChatStore.getMessages()});
}

// HANDLING OF FORMS, DATA SUBMISSION ECT
// =====================================================
handleChange(e) {
    this.setState({chat__message_input: e.target.value});
}

handleSubmit(e) {
    e.preventDefault();

    if (this.state.chat__message_input == "") {
        // create some error here later
        return
    };

    ChatActions.addMessage({
        username: "username",
        message: this.state.chat__message_input,
        message_id: uid("msg-"),
    });  

    // reset input field
    this.setState({chat__message_input: ""});
}
...

这是商店

var CHANGE = "change_event";

class ChatStoreClass extends EventEmitter {
    constructor() {
        super();
        this._messages = [
            {
                username: "christian",
                message: "hello world",
                message_id: "msg-12kjds8",
            }
        ];
    }  

    init() {
        this._emitChange();
    }

    getMessages() {
        return this._messages;
    }

    _emitChange() {
        this.emit(CHANGE);
    }


}

var ChatStore = new ChatStoreClass;

AppDispatcher.register(function(payload){
    switch(payload.actionType) {
        case ChatConstants.ADD_MESSAGE:
            ChatStore._messages.push(payload.action);
            break;
    }
})

export default ChatStore;

ChatStore._messages.push(payload.action); 正在更新视图上的状态而不发出更改事件:(

道歉,如果说得不好。我通常不会向其他人解释我的编程问题,更不用说任何人了。

感谢您抽出宝贵时间阅读本文。

1 个答案:

答案 0 :(得分:1)

getMessages()正在将引用返回到商店中的邮件列表,而不是邮件本身。 SetState(例如,在您的handleSubmit中)始终触发对组件的更新;因为您已将this.state.chat__messages设置为对商店消息列表的引用(而不是将其消息添加到您的chat_messages数组中),所以它始终与商店保持同步。

getMessages() {
    return [...this._messages]; // or w/o ES6 -> return Array.apply([], this._messages)
}

应该给你预期的效果。

我确信这是无意的,但部分困惑在于,除非通过SetState,否则你永远不应该改变状态。通过使用对可变数据的引用,您可以获得意想不到的效果,这非常难以追踪。