为什么我的应用程序状态在没有来自商店的更改事件的情况下更新 - 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
。通过使用对可变数据的引用,您会得到意想不到的效果,这种效果很难追踪。
长话短说;博士
这是我解释(糟糕)问题的视频:
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
。通过使用对可变数据的引用,您会得到意想不到的效果,这种效果很难追踪。