反应重新渲染不显示更新的状态数组
React re-render not showing updated state array
我正在事件处理函数中更新状态(将新对象添加到状态数组)。
const handleIncomingData = (data) => {
setState(state => {
var _state = state
if (_state.someDummyStateValue === 1234) {
_state.arr.push({ message: data.message })
}
return _state
})
}
React.useEffect(() => {
socket.on('data', handleIncomingData)
return()=>{
socket.off('data', handleIncomingData)
}
},[])
我正在以这种方式更新状态,因为事件处理函数无法访问最新的状态值。 console.log(state) 显示更新后的状态,但在重新渲染后不显示新添加的对象。此外,当同一事件再次触发时,会显示先前收到的数据,但不会显示最新的数据。以这种方式更新状态有什么问题吗?
尝试使用默认的方式来制作状态它是首选,干净和简单的编码方式
const [message, setMessage] = useState([])
const handleIncomingData = data => {
let newMessage = message;
if (data.message.somevalue === 1234){
newMessage.push(data.message);
setMessage(newMessage)
}
}
React.useEffect(() => {
socket.on('data', handleIncomingData)
return()=>{
socket.off('data', handleIncomingData)
}
},[message])
是的,这是错误的......你应该永远不要直接在状态下进行操作......
如果您想将消息附加到您的消息数组,正确的片段代码将是:
const [messages, setMessage] = useState([])
const handleIncomingData = useCallback(
data => {
if (messages.someDummyStateValue === 1234) {
setMessage([...messages,{message:data.message}])
}
// do nothing
},[messages])
React.useEffect(() => {
socket.on('data', handleIncomingData)
return()=>{
socket.off('data', handleIncomingData)
}
},[handleIncomingData])
这样我就不会对任何状态进行任何操作,我只是用新状态替换旧状态(这只是带有新消息的旧状态)
你总是想在数组状态下操作数据,你不应该直接在状态下进行操作...
javascript 中的对象是通过引用复制的(内存中存储它的地址)。
当您执行以下操作时:
let obj1 = {}
let obj2 = obj1;
obj2
与 obj1
.
具有相同的引用
在您的例子中,您是直接复制状态对象。当您调用 setState
时,它会触发重新渲染。如果前一个渲染的值与当前渲染的值相同,React 将不会更新。因此,您需要创建一个新的状态副本。
试试这个:
setState(prevValue => [...prevValue, {message: data.message}])
为了更好地说明我的观点,这里有一个代码框:https://codesandbox.io/s/wild-snowflake-vm1o4?file=/src/App.js
我正在事件处理函数中更新状态(将新对象添加到状态数组)。
const handleIncomingData = (data) => {
setState(state => {
var _state = state
if (_state.someDummyStateValue === 1234) {
_state.arr.push({ message: data.message })
}
return _state
})
}
React.useEffect(() => {
socket.on('data', handleIncomingData)
return()=>{
socket.off('data', handleIncomingData)
}
},[])
我正在以这种方式更新状态,因为事件处理函数无法访问最新的状态值。 console.log(state) 显示更新后的状态,但在重新渲染后不显示新添加的对象。此外,当同一事件再次触发时,会显示先前收到的数据,但不会显示最新的数据。以这种方式更新状态有什么问题吗?
尝试使用默认的方式来制作状态它是首选,干净和简单的编码方式
const [message, setMessage] = useState([])
const handleIncomingData = data => {
let newMessage = message;
if (data.message.somevalue === 1234){
newMessage.push(data.message);
setMessage(newMessage)
}
}
React.useEffect(() => {
socket.on('data', handleIncomingData)
return()=>{
socket.off('data', handleIncomingData)
}
},[message])
是的,这是错误的......你应该永远不要直接在状态下进行操作...... 如果您想将消息附加到您的消息数组,正确的片段代码将是:
const [messages, setMessage] = useState([])
const handleIncomingData = useCallback(
data => {
if (messages.someDummyStateValue === 1234) {
setMessage([...messages,{message:data.message}])
}
// do nothing
},[messages])
React.useEffect(() => {
socket.on('data', handleIncomingData)
return()=>{
socket.off('data', handleIncomingData)
}
},[handleIncomingData])
这样我就不会对任何状态进行任何操作,我只是用新状态替换旧状态(这只是带有新消息的旧状态)
你总是想在数组状态下操作数据,你不应该直接在状态下进行操作...
javascript 中的对象是通过引用复制的(内存中存储它的地址)。 当您执行以下操作时:
let obj1 = {}
let obj2 = obj1;
obj2
与 obj1
.
在您的例子中,您是直接复制状态对象。当您调用 setState
时,它会触发重新渲染。如果前一个渲染的值与当前渲染的值相同,React 将不会更新。因此,您需要创建一个新的状态副本。
试试这个:
setState(prevValue => [...prevValue, {message: data.message}])
为了更好地说明我的观点,这里有一个代码框:https://codesandbox.io/s/wild-snowflake-vm1o4?file=/src/App.js