问题
...inside a dispatch, in the path: "chat.messages.0' Take a look at the reducer(s) handling the action {'type': 'chat', 'payload': {'sender': 'you', 'body': 'foo'}}`
My reducer:
chatMessage.js:
export default (state, action) => {
return Object.assign({}, {
...state,
messages: [...state.messages, action.payload]
})
}
Interestingly, if I use messages=[]
in my Chat component, I don't get this error.
export default class Chat extends React.Component {
state = {...this.props.data, input: "", toggle: false}
_renderItem = ({item}) => {
return <ChatMessageRow data={item} />
}
render() {
// var {messages} = this.state
var messages = []
return (
<View style={styles.container}>
<FlatList
inverted
renderItem={this._renderItem}
style={styles.logWrapper}
data={messages.reverse()}
extraData={this.state.toggle}
/>
from my main view, which is bound to Redux:
return (...other views... check if tabIndex == 1, show <Chat data={this.props.chat} ... />
I ran into an issue earlier with the FlatList rendering in Chat not updating and I had to do a
this.setState({messages: messages.push(newMessage), toggle: !this.state.toggle})
to update the state so the Flat List would recognize it's changed.
Now I am loading my data from a Chat store using connect and redux, then passing that data into the component.
I get the error when I try to reload the Chat component after adding chat messages. Weirdly I can get one to update but after adding one it will not show others.
At first I think this is a problem in my reducer so I rewrite the reducer to use the Object assign and array spread operator.
Now I think it is related to the rendering which is unexpected.
How do I debug this?
EDIT:
It's not "it works with adding 1 message". It's - I can bring the view out of focus and back into focus one time. So..
Open Chat Tab Observer 1 message Add N messages to store using redux actions Change tabs, revert back to Chat Observer N messages added Add M messages Change tabs, click back to Chat tab Error shows
EDIT:
I tried
using ...spread, but redux still throws warning about state mutation 's suggestion doing
export default (state, action) => {
return Object.assign({}, {
...state,
messages: state.messages.map(value => Object.assign({}, value)).concat(action.payload)
})
}
in my reducer, same error.
EDIT:
My reducer is update to chatMessage.js
I think the issue is in how I'm calling this.
I am writing a websocket controller. I don't need to wait for a response when I send a message like I would with an HTTP response.
My websocket controller:
onMessage = ({data}) => {
const json = JSON.parse(data)
if (json) {
if (json.status) {
const reducer = this.stateFilters[json.status]
if (reducer) {
reducer(json.body)
} else {
console.log("No reducer")
}
}
}
}
the websocket controller is created in my View component:
my main view
import {ChatStateFilters} from '../../reducers/chat'
const mapDispatch = { chatMessage }
this.wsController = new WebSocketController({
stateFilters: {chatMessage: this.props.chatMessage},
from the chat reducer file (that contains the chatMessage reducer)
Those state filters get created when I create my slice.
The value of stateFilter['chatMessage'] -- which is the value of what gets bound to my View's prop in mapDispatchToProp
is this function:
let fn = (payload) => {
return dispatch => {
dispatch(stateFilters[actionName](payload))
}
}
exportedStateFilters[actionName] = fn
I think the problem is somewhere in here^... somehow the dispatch is firing, updating state but redux doesn't know the dispatch is finished
EDIT 2:
I thought the lack of async may have been an issue. So I changed the stateFilter (the fn that gets bound to my prop in the view) to this:
let fn = (payload) => {
return dispatch => {
post("", {}, true)
.then(response => {
dispatch(stateFilters[actionName](payload))
})
.catch(error => {
dispatch(stateFilters[actionName](payload))
})
}
}
and now it works a few more times.. then gives me the error "A state mutation was detected between dispatches".
My chat message reducer is still
export default (state, action) => {
let messages2 = Object.assign([], [...state.messages, action.payload])
return Object.assign({}, {...state, messages: messages2 })
}
so why is this error happening?
来源:https://stackoverflow.com/questions/58120646/a-state-mutation-was-detected-inside-a-dispatch-not-in-between-dispatch