为什么我的应用程序状态在没有来自商店的更改事件的情况下更新 - flux

Why is my application state updating without change event from store - flux

长话短说;博士
这是我解释(糟糕)问题的视频:
https://www.youtube.com/watch?v=lJogEfYYHRo&feature=youtu.be

我正在使用 flux 在 Web 应用程序上制作聊天功能。 我有一家商店,里面有一个名为 messages 的数组。正如预期的那样,每当商店发生变化时,商店都会发出更改事件,视图上的侦听器会听到它并使用商店中的 getter 方法更新状态。

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

这是 视图 和所有相关代码

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); 正在更新视图上的状态而没有发出更改事件:(

如果解释不当,我们深表歉意。我不是一个经常向其他人解释我的编程问题的人,更不用说任何人了。

感谢您花时间阅读本文。

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

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

应该能达到你期望的效果。

我确定这是无意的,但部分混淆是你永远不应该改变状态,除非通过 SetState。通过使用对可变数据的引用,您会得到意想不到的效果,这种效果很难追踪。