简体   繁体   English

反应重新渲染未显示更新的 state 数组

[英]React re-render not showing updated state array

I am updating state(adding new object to state array) in event handler function.我正在事件处理程序 function 中更新状态(将新的 object 添加到 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)
  }
},[])

I am updating state in this manner as event handler function is not having access to latest state values.我正在以这种方式更新 state,因为事件处理程序 function 无法访问最新的 state 值。 console.log(state) shows updated state but after re-render newly added object is not displayed. console.log(state) 显示更新的 state 但重新渲染后新添加的 object 不显示。 Also when same event fires again previously received data is displayed but not the latest one.同样,当再次触发相同的事件时,会显示先前接收到的数据,但不会显示最新的数据。 Is there something wrong with updating state in this manner?以这种方式更新 state 有什么问题吗?

Object in javascript are copied by reference (the address in the memory where its stored). javascript 中的 Object 是通过引用复制的(memory 中存储的地址)。 When you do some thing like:当您执行以下操作时:

let obj1 = {}
let obj2 = obj1;

obj2 has the same reference as obj1 . obj2obj1具有相同的引用。

In your case, you are directly copying the state object.在您的情况下,您直接复制 state object。 When you call setState , it triggers a re-render.当您调用setState时,它会触发重新渲染。 React will not bother updating if the value from the previous render is the same as the current render.如果前一个渲染的值与当前渲染的值相同,React 不会打扰更新。 Therefore, you need to create a new copy of your state.因此,您需要创建 state 的新副本。

Try this instead:试试这个:

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

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

Try using the default way of making states it is preferred, clean and simple codeing way尝试使用默认的状态生成方式,它是首选、干净和简单的编码方式

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

Yes, it's wrong... You should never do operations directly in the state... If you want to append messages to your array of messages, the correct snippet code would be:是的,这是错误的...您永远不应该直接在 state 中进行操作...如果您想将 append 消息添加到您的消息数组中,正确的代码段代码将是:

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

This way I'm not doing any operation to any state, I'm just replace the old state, with the new one (which is just the old one with a new message)这样我就不会对任何 state 进行任何操作,我只是用新的 state 替换旧的(这只是带有新消息的旧的)

Always you want to manipulate data in an array state, you should never do operations directly in the state...总是你想操作数组 state 中的数据,你不应该直接在 state 中进行操作...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM