[英]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 将尝试通过身份检查( ===
)而不是通过深度相等检查(即lodash
的isEqual
)来查找更改。 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.