简体   繁体   English

在服务器响应后 React 不会重新渲染组件

[英]React doesn't rerender Component after server response

I have a Chat app.我有一个聊天应用程序。 I need to rerender the message item (partial Component) after moderator clicks "Delete".版主点击“删除”后,我需要重新渲染消息项(部分组件)。 So I send a request to the server to make changes in certain message in array of all messages, and response with updated array.因此,我向服务器发送请求以更改所有消息数组中的某些消息,并使用更新的数组进行响应。 Next I set the new array to State using Reducer.接下来,我使用 Reducer 将新数组设置为 State。 As I can see in the logs, state updates after every response, but React doesn't rerender the message item Component.正如我在日志中看到的,每次响应后状态都会更新,但 React 不会重新呈现消息项 Component。

Besides, the same code works when I create the new message (example below).此外,当我创建新消息时,相同的代码也有效(下面的示例)。 Changes on the screen appear only after this sequence: send new message - click "Delete" - send another new message.屏幕上的更改仅在此序列之后出现:发送新消息 - 单击“删除” - 发送另一条新消息。

Request to the server on "Delete" click:向服务器请求“删除”点击:

axios
  .patch(`${serverName}/messages/${patchTarget}/${messageId}`)
  .then((response) => {
    let fetchedMessages = [...response.data];
    dispatch(setMessages({ fetchedMessages, flag }));
  });

Reducer:减速器:

setMessages(state, action) {
  const flag = action.payload.flag;
  // state.showMessages is responsible for showed messages
  state[flag] = [...action.payload.fetchedMessages];
  state.showMessages[flag] = [...state[flag]];
}

Server:服务器:

let MESSAGES = {
  DISPUTE: [{}],
  SPEC: [{}]
};

app.get("/messages/:target", (req, res) => {
  const fetchTarget = req.params.target;
  res.status(200).json(MESSAGES[fetchTarget as keyof typeof MESSAGES]);
});

app.post("/messages/:target", (req, res) => {
  const newMessage = req.body;
  const pushTarget = req.params.target;
  MESSAGES[pushTarget as keyof typeof MESSAGES].push(newMessage);
  res.status(200).json(MESSAGES[pushTarget as keyof typeof MESSAGES]);
});

app.patch("/messages/:target/:id", (req, res) => {
  const patchTarget = req.params.target;
  const messageId = Number(req.params.id);
  const element = MESSAGES[patchTarget as keyof typeof MESSAGES][messageId];
  if (!element.deletedText) element.deletedText = element.text;
  if (!element.deleted) element.deleted = !element.deleted;
  element.text = "Message has been deleted by moderator";
  
  res.status(200).json(MESSAGES[patchTarget as keyof typeof MESSAGES]);
});

Working code in another Component where I create a new message and send it:我在另一个组件中创建一条新消息并发送它的工作代码:

axios
  .post(`${serverName}/messages/${pushTarget}`, newMessageFunc())
  .then((response) => {
  let fetchedMessages = [...response.data];
  dispatch(setMessages({ fetchedMessages, flag }));
});

Why does it work when I create a new message, but it doesn't when I try to edit it?为什么当我创建新消息时它可以工作,但当我尝试编辑它时却不行?

As long as the data are all right, most likely the issue will be on the front-end side.只要数据没问题,很可能问题出在前端。

There is a lot of unknowns how does this code actually work, but most likely it's the problem with detecting the change in state.这段代码实际上是如何工作的还有很多未知数,但很可能是检测状态变化的问题。

When you have your reducer:当你有你的减速器时:

setMessages(state, action) {
  const flag = action.payload.flag;
  // state.showMessages is responsible for showed messages
  state[flag] = [...action.payload.fetchedMessages];
  state.showMessages[flag] = [...state[flag]];
}

The arrays have new identity, but the showMessages object is still the same - it may cause the change being not detected.数组具有新的标识,但showMessages对象仍然相同 - 这可能会导致未检测到更改。 The React will try to find a change by identity check ( === ), not by deep equality check (ie lodash 's isEqual ). React 将尝试通过身份检查( === )而不是通过深度相等检查(即lodashisEqual )来查找更改。 Assuming that previous state is prevState and the state after reducer is nextState :假设之前的状态是prevState ,reducer 之后的状态是nextState

prevState[flag] === nextState[flag] // false
prevState.showMessages === nextState.showMessages // true
prevState.showMessages[flag] === nextState.showMessages[flag] // false

Most likely, if you'll change your reducer to create a new showMessages object, it will work fine:最有可能的是,如果您更改减速器以创建一个新的showMessages对象,它将正常工作:

setMessages(state, action) {
  const flag = action.payload.flag;
  // state.showMessages is responsible for showed messages
  state[flag] = [...action.payload.fetchedMessages];
  state.showMessages = {
    ...state.showMessages,
    [flag]: [...state[flag]],
  };
}

After that, all objects will be detected as different from the previous state:之后,所有对象都将被检测为与之前的状态不同:

prevState[flag] === nextState[flag] // false
prevState.showMessages === nextState.showMessages // false
prevState.showMessages[flag] === nextState.showMessages[flag] // false

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

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