Javascript 将初始化对象传递给setState React

Javascript 将初始化对象传递给setState React,javascript,reactjs,closures,Javascript,Reactjs,Closures,我正在一个网站上实现聊天功能。提交消息时,新消息将添加到存储会话期间发送的所有聊天消息的阵列中 <form onSubmit={handleSubmit} id="chatForm" className="chat-form border-top" > <input value={state.fieldValue} ref={chatField} type="

我正在一个网站上实现聊天功能。提交消息时,新消息将添加到存储会话期间发送的所有聊天消息的阵列中

<form
    onSubmit={handleSubmit}
    id="chatForm"
    className="chat-form border-top"
  >
    <input
      value={state.fieldValue}
      ref={chatField}
      type="text"
      className="chat-field"
      id="chatField"
      placeholder="Type a message…"
      autoComplete="off"
      onChange={handleFieldChange}
    />
  </form>
我这样做的第一个方法如下:

const newState = { ...state };

newState.chatMessages.push({
  message: state.fieldValue,
  username: appState.user.username,
  avatar: appState.user.avatar,
});
newState.fieldValue = "";

setState(newState);
其结果如下:

console.log是从初始渲染打印的,但不会再次打印。但是,会显示新消息,指示某些状态更新已生效,并且聊天消息已添加到阵列中

更新状态的第二种方法是将对象文本直接传递给setState函数:

setState({
  ...state,
  chatMessages: [
    ...state.chatMessages,
    {
      message: state.fieldValue,
      username: appState.user.username,
      avatar: appState.user.avatar,
    },
  ],
  fieldValue: "",
});
这将导致预期的行为:

在此状态更新中,console.log会在每次更新后打印出正确的状态


我的问题是react的状态更新为什么会这样。我理解直接更改状态的易变性,但是为什么第一种更新状态的方法会将我的消息添加到队列中,而不是注册到useEffects侦听更改?

第一种方法不是注册到
useEffect
,因为您直接操作状态而不是使用状态设置器。从技术上讲,您可以在使用
useState
时直接对状态项进行更改(假设您没有严格的linting),但如果在实际应用程序中使用,它将非常不可靠,并且是一种负担

您可能还想考虑UsReRever,它是由

重新记录的。 另一个选项是useReducer,它更适合管理包含多个子值的状态对象


欢迎来到SO!是的,第一个版本是不正确的,因为你正在改变不可预测的状态。不能保证它不会意外工作或部分工作,但它基本上是禁止的,并且可能对行为的推理没有太大的帮助。
setState({
  ...state,
  chatMessages: [
    ...state.chatMessages,
    {
      message: state.fieldValue,
      username: appState.user.username,
      avatar: appState.user.avatar,
    },
  ],
  fieldValue: "",
});