You*_*reo 5 javascript reactjs redux
上下文:我正在尝试制作一个使用 react redux 和 socket.io 的 Web 客户端。该设计的灵感来自 whatsapp,老实说,这只是我用来学习 react 和 redux 的一个有趣的小项目。
主要问题是我有一个 ActiveChat 组件,它不会在商店更改和识别更改时重新呈现。Redux Devtools 甚至显示了差异和状态变化。
该组件已连接:
//Redux Mapping for Store and Actions
const mapStateToProps = state => {
return { activeChat: state.activeChat };
};
const mapDispatchToProps = dispatch => {
return {
updateActiveChat: chat => dispatch(updateActiveChat(chat))
}
}
const activeChatConnected = connect(mapStateToProps,mapDispatchToProps)(ActiveChat)
export default activeChatConnected;
Run Code Online (Sandbox Code Playgroud)
我有一个想法,我可能不会以某种方式保持状态纯洁,因为这是我的第一个在 javascript 中使用状态不变性的探戈,并希望我能得到社区的帮助
代码可在此处获得:https : //github.com/YourFavouriteOreo/ChatClient(始终欢迎反馈,因为我正在努力提高 JavaScript 水平)
有问题的代码片段具体是:
# src/reducers
const rootReducer = (state = initialState,action) => {
switch(action.type){
case SELECT_ACTIVE:
// Select Active Chat so as to display chat content
var newActive = Object.assign(state.chats[action.payload.index])
newActive["index"]= action.payload.index
return {...state,activeChat:newActive}
case UPDATE_CHAT:
// Update store with new Chat Content
var chats = Object.assign(state.chats)
chats[state.activeChat.index].chatLogs.concat(action.payload)
return {...state,chats}
default:
return state
}
}
Run Code Online (Sandbox Code Playgroud)
我目前通过在操作后立即设置状态来修复此问题,但这并不理想,因为一旦我将使用 sockets , setState 为 async 可能会导致某些问题。
inputHandler = logs => {
// Handle Input from chatInput
var newState = this.state.chatLogs;
newState.push(logs);
//Redux Action
this.props.updateActiveChat(logs)
console.log(this.state.chatLogs);
// BAD HOTFIX
this.setState({});
};
Run Code Online (Sandbox Code Playgroud)
编辑:这是被问到的,所以我会在这里添加它。该return {...state,chats}做的,其实GET结果为回报{...state, chats:chats}
编辑2:
// actions
import {SELECT_ACTIVE, UPDATE_CHAT} from "../constants/action-types"
export const selectActiveChat = selected => ({type: SELECT_ACTIVE, payload:selected})
export const updateActiveChat = chat => ({type: UPDATE_CHAT, payload:chat})
Run Code Online (Sandbox Code Playgroud)
编辑 3:
// activeChat 组件的渲染函数
render() {
if (this.state != null){
return (
<div className="column is-8 customColumn-right">
<div className="topColumn">
<h1 style={{fontFamily:"Quicksand,sans-serif", fontWeight:"bold", fontSize:"1.1rem"}}> {this.state.chatName} </h1>
<p style={{fontFamily:"Roboto,sans-serif",marginLeft: "0.75rem",lineHeight:"1"}}> Chat Participants </p>
</div>
<ChatContent
chatLogs={this.props.activeChat.chatLogs}
isTyping={this.state.isTyping}
/>
<ChatInput postSubmit={this.inputHandler} />
</div>
);
}
else {
return <NoActiveChat/>
}
}
componentWillReceiveProps(newProps){
// Change Props on Receive
console.log("das new props");
this.setState({
chatName: newProps.activeChat.chatName,
chatLogs: newProps.activeChat.chatLogs,
isTyping: newProps.activeChat.isTyping
})
}
Run Code Online (Sandbox Code Playgroud)
我设法通过在减速器中以不同方式执行 concat 来修复它。我不明白这如何改变最终结果,因为对象仍然发生变化,但这似乎解决了。
代替 :
case UPDATE_CHAT:
// Update store with new Chat Content
console.log("Update chat action executed");
var chatState = Object.assign({},state)
chatState.chats[state.activeChat.index].chatLogs.concat(action.payload)
return {...chatState}
Run Code Online (Sandbox Code Playgroud)
我做了:
case UPDATE_CHAT:
// Update store with new Chat Content
console.log("Update chat action executed");
var chatState = Object.assign({},state)
chatState.chats[state.activeChat.index].chatLogs = chatState.chats[state.activeChat.index].chatLogs.concat(action.payload)
return {...chatState}
Run Code Online (Sandbox Code Playgroud)
编辑:事实证明, Object.assign() 执行了浅克隆,这意味着嵌套对象是引用而不是副本。如果你想做一个 deepClone 。您可以使用 lodash 中的cloneDeep,我在后来使用其他函数时遇到的其他问题中意识到了这一点。
我的解决方案中的新案例处理程序如下。
_ 是我对 lodash 的导入
case UPDATE_CHAT:
// Update store with new Chat Content
console.log("Update chat action executed");
var chatState = _.cloneDeep(state)
chatState.chats[state.activeChat.index].chatLogs = chatState.chats[state.activeChat.index].chatLogs.concat(action.payload)
return {...chatState}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1446 次 |
| 最近记录: |