我有以下代码:
{
"_id": "5f2bf26783f65d33026ea592",
"lendingpartner": {
/* some keys here */
},
"loans": [
{
"loanid": 43809,
"loanamount": 761256,
"jewels": [
"5f2bf26783f65d33026ea593",
"5f2bf26783f65d33026ea594"
"5f2bf26783f65d33026ea595"
],
}
]
}
我想知道为什么在第1点设置setMessages之后,当我执行控制台日志时,它似乎没有更新。当我调用addMessageWithTimer时,这变成一种怪异的行为,因为当它调用removeMessage时,它不能正确地删除我期望的消息。
能否请您解释一下该怎么做?
答案 0 :(得分:2)
就像类组件中的setState
一样,useState
的更新功能不会立即更新状态,它们会安排状态进行更新。
当您调用setMessages
时,它会做出反应以安排App
的新渲染,该渲染将再次执行App
函数,而useState
将返回{ {1}}。
如果从纯粹的JS角度考虑它,messages
不能进行更改:它只是一个局部变量,(甚至是一个messages
)。调用非本地函数不会导致更改本地变量的值,而JS不能那样工作。
答案 1 :(得分:0)
@Retsam的解释是正确的。
如果您不在addMessageWithTimer中使用setTimeout,我认为您会遇到问题。是不是但是现在,这是正确的。
如果您不想设置5秒的计时器,但仍然希望其正常运行,请设置0秒的计时器。仍然可以。
答案 2 :(得分:0)
您看到什么奇怪的行为?
在尝试您的代码时,我可以在5秒钟后删除添加的消息。
import React, { useState } from "react";
import "./styles.css";
export default function App() {
let bodyText = "";
const [lastMessageId, setLastMessageId] = useState(0);
const [messages, setMessages] = useState([]);
const addMessage = (body, type) => {
if (body === "") return;
const newMessage = {
id: lastMessageId + 1,
type: type,
body: body
};
setLastMessageId(newMessage.id);
setMessages([...messages, newMessage]);
bodyText = "";
return newMessage.id;
};
// remove a message with id
const removeMessage = (id) => {
const filter = messages.filter((m) => m.id !== id);
console.log("point 2", filter);
setMessages(filter);
};
// add a new message and then remove it after some seconds
const addMessageWithTimer = (body, type = "is-primary", seconds = 5) => {
const id = addMessage(body, type);
setTimeout(() => removeMessage(id), seconds * 1000);
};
console.log("point 1", messages);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<input onChange={(e) => (bodyText = e.target.value)} />
<button onClick={(e) => addMessage(bodyText, "is-primary")}>
Add messsage
</button>
<button onClick={(e) => addMessageWithTimer(bodyText, "is-primary", 5)}>
Add temp messsage
</button>
{messages.map((message, id) => {
return (
<div key={id}>
<p>
{message.id} {message.body}
</p>
</div>
);
})}
</div>
);
}
答案 3 :(得分:0)
@Retsam的回答非常有用,因为我能够理解问题并找到合适的解决方案。
这是我找到的解决方案:
export default function App() {
const [lastMessageId, setLastMessageId] = useState(0);
const [messages, setMessages] = useState([]);
const addMessage = (body, type="is-primary") => {
const newMessage = {
id: lastMessageId + 1,
type: type,
body: body
};
setLastMessageId(newMessage.id)
setMessages([...messages, newMessage]);
return newMessage.id;
}
// delete messages after 5 seconds
useEffect(() => {
if (!messages.length) return;
const timer = setTimeout(() => {
const remainingMessages = [...messages];
remainingMessages.shift();
setMessages(remainingMessages);
}, 5*1000);
return () => clearTimeout(timer);
}, [messages]);
return (
...
);
}