开发一个带有加载器的聊天应用程序,以等待接收响应。根据控制台.log在应用程序中,isLoading
状态会正确更改,但是在接收者的对象中,isLoaded
键不会更新,只会显示分配状态的初始值。因此,加载程序不会显示在 UI 中。您可以在下面找到代码。
const [messagesList, setMessagesList] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [currentMessage, setCurrentMessage] = useState("");
const handleSend = () => {
if (currentMessage !== "") {
setIsLoading(true);
setMessagesList([
...messagesList,
{
dataType: "text",
item: {
id: uuidv4(),
type: "sender",
message: currentMessage,
},
},
]);
axios
.post(`${BASE_URL}`, {
data: currentMessage,
})
.then((response) => {
setIsLoading(false);
setMessagesList([
...messagesList,
{
dataType: "text",
item: {
id: uuidv4(),
type: "sender",
message: currentMessage,
},
},
{
dataType: "text",
item: {
id: uuidv4(),
type: "reciever",
isLoaded: isLoading,
message: response.data.data.answers
},
},
]);
setCurrentMessage("");
})
.catch((error) => {
setIsLoading(true);
setMessagesList([
...messagesList,
{
dataType: "text",
item: {
id: uuidv4(),
type: "sender",
message: currentMessage,
},
},
{
dataType: "text",
item: {
id: uuidv4(),
type: "reciever",
isLoaded: isLoading,
message: "something went wrong"
},
},
]);
setCurrentMessage("");
setIsLoading(false);
});
setCurrentMessage("");
}
};
return (
<>
<textarea
type="text"
placeholder="ask me ..."
rows={1}
cols={1}
onChange={(e) => setCurrentMessage(e.target.value)}
value={currentMessage}
autoFocus
/>
<button onClick={ ()=> handleSend }> Sned </button>
{messagesList.map(({ dataType, item }) => {
if (dataType === "text") {
if (item.type === "sender") {
return (
<p style={{ color: "red" }}>{item.message}</p>
);
}
if (item.type === "reciever") {
if (item.isLoaded) {
return <p> laoding</p>;
} else {
return <p> {item.message} </p>;
}
}
}
})}
</>
)
这里的问题可能源于您在通过setLoading
设置后立即使用isLoading
的值。
在 React 中设置状态就像一个异步函数.
这意味着当你设置状态并尝试使用它的值时,
你可能会得到该状态的先前值。
在这种情况下,请尝试使相关的messagesList
值独立于isLoading
。
例:
.then((response) => {
const newIsLoading = false;
setIsLoading(newIsLoading);
setMessagesList([
...messagesList,
{
// Some code...
},
{
dataType: "text",
item: {
id: uuidv4(),
type: "reciever",
isLoaded: newIsLoading,
message: response.data.data.answers
},
},
]);
setCurrentMessage("");
})
状态更新是异步调度的。这意味着当你的代码到达你的第二个setMessagesList
时,这是最后一个考虑并因此调度的代码。
setMessagesList([...]) // to be dispatched
axios.post((resp)=> resp.json().then(data=> setMessagesList([...]) //oops, not that one, this one
可能,您的控制台与此有关.log。如果要查看更新的值,则需要将其添加为效果
useEffect(()=> console.log(messagesList), [messagesList])
最后,您可能希望通过.then
和.catch
将共享代码移动到.finally
:
.finally(()=> {
setCurrentMessage("");
setIsLoading(false);
}