反应重新渲染不显示更新的状态数组

时间:2021-01-24 11:56:31

标签: javascript reactjs react-state

我正在事件处理函数中更新状态(向状态数组添加新对象)。

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) 显示更新的状态,但在重新渲染新添加的对象后不显示。此外,当同一事件再次触发时,会显示先前接收到的数据,但不会显示最新的数据。以这种方式更新状态有什么问题吗?

3 个答案:

答案 0 :(得分:1)

javascript 中的对象是通过引用(存储它的内存中的地址)复制的。 当您执行以下操作时:

let obj1 = {}
let obj2 = obj1;

obj2obj1 具有相同的引用。

在您的情况下,您是直接复制状态对象。当您调用 setState 时,它会触发重新渲染。如果前一个渲染的值与当前渲染相同,React 不会更新。因此,您需要为您的状态创建一个新副本。

试试这个:

setState(prevValue => [...prevValue, {message: data.message}])

为了更好地说明我的观点,这里有一个代码框:https://codesandbox.io/s/wild-snowflake-vm1o4?file=/src/App.js

答案 1 :(得分:0)

尝试使用默认的状态设置方式,它是首选、干净和简单的编码方式

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])

答案 2 :(得分:0)

是的,这是错误的...您应该永远不要直接在状态下进行操作... 如果您想将消息附加到您的消息数组中,正确的代码片段应该是:

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])

这样我就不会对任何状态做任何操作,我只是将旧状态替换为新状态(只是带有新消息的旧状态)

总是想在数组状态下操作数据,千万不要直接在状态下操作...