我正在制作一個簡單的表單來編輯應用程式,使用從 API 回傳的資料設定應用程式名稱和描述的初始狀態。
目前,當提交表單時,初始資料似乎記錄為未定義,名稱和描述被設定為未定義,這發生在第一次渲染中(我已經在日志所在的代碼中評論過)
如何確保名稱和描述的初始狀態具有最新資訊?是過度渲染的問題嗎?
感謝您查看,任何幫助將不勝感激。
import React, { useState, useContext, useEffect } from "react";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
import Container from "@material-ui/core/Container";
import SaveIcon from "@mui/icons-material/Save";
import CloseIcon from "@mui/icons-material/Close";
import { makeStyles } from "@material-ui/styles";
import TextField from "@material-ui/core/TextField";
import { Grid } from "@mui/material";
import { useDispatch } from "react-redux";
import { updateApp, updateSelectedApp } from "../../services/reducers/apps";
import { EndpointContext } from "../../baxios/EndpointProvider";
import { useParams } from "react-router-dom";
export default function EditApp() {
const { appid } = useParams();
const classes = useStyles();
const dispatch = useDispatch();
const endpoints = useContext(EndpointContext);
const [selectedApp, setSelectedApp] = useState({});
const [isLoaded, setIsLoaded] = useState(false); // <--- Is there anyway I can also remove this useState? without this the default values in the forms dont populate
useEffect(() => {
async function fetchApp() {
await endpoints.appEndpoints.get(appid).then((response) => {
if (response.status === 200) {
setSelectedApp(response.data);
setIsLoaded(true);
}
});
}
fetchApp();
}, []);
useEffect(() => {
console.log(selectedApp);
}, [selectedApp]);
const [name, setName] = useState(selectedApp.name);
const [description, setDescription] = useState(selectedApp.description);
console.log("---", name, selectedApp.name); // <--- The page renders 3 times, each render log looks like this
// 1st render - --- undefined, undefined
// 2nd render - --- undefined, Appname
// 3rd render - --- undefined, Appname
const handleSubmit = (e) => {
e.preventDefault();
console.log("triggered", name, description); // <--- This logs (triggered, undefined, undefined)
if (name && description) {
const body = { name: name, description: description };
endpoints.appEndpoints.put(selectedApp.id, body).then((response) => {
if (response.status === 200) {
dispatch(updateApp(response.data));
setSelectedApp(response.data);
setName(selectedApp.name);
setDescription(selectedApp.description);
}
});
}
};
return (
<div style={{ margin: 100, marginLeft: 350 }}>
{isLoaded ? (
<Container size="sm" style={{ marginTop: 40 }}>
<Typography
variant="h6"
color="textSecondary"
component="h2"
gutterBottom
>
Edit App
</Typography>
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
<TextField
className={classes.field}
onChange={(e) => setName(e.target.value)}
label="App Name"
variant="outlined"
color="secondary"
fullWidth
required
size="small"
defaultValue={selectedApp.name}
error={nameError}
/>
<TextField
className={classes.field}
onChange={(e) => setDescription(e.target.value)}
label="Description"
variant="outlined"
color="secondary"
rows={4}
fullWidth
required
size="small"
defaultValue={selectedApp.description}
error={descriptionError}
/>
<Grid container spacing={2}>
<Grid item>
<Button
// onClick={handleSubmit}
type="submit"
color="primary"
variant="contained"
endIcon={<SaveIcon />}
>
Save
</Button>
</Grid>
</Grid>
</form>
</Container>
) : (
<></>
)}
</div>
);
}
uj5u.com熱心網友回復:
使用 時const [name, setName] = useState(defaultName),如果defaultName在將來的渲染中更新,則該name值將不會更新為此最新值。
因此,在您的情況下,您可以進行以下更改:
const [name, setName] = useState();
const [description, setDescription] = useState();
useEffect(() => {
setName(selectedApp.name)
setDescription(selectedApp.description)
}, [selectedApp])
)
uj5u.com熱心網友回復:
- 名稱和描述未定義
您的 selectedApp 被初始化為一個空物件。您的 useEffect 觸發請求以檢索該資料,但頁面在獲得回應之前呈現一次。有幾種方法可以處理這個問題。您可以做任何事情,從在欄位上顯示加載圖示到為欄位設定默認值,直到呼叫帶有 [selectedApp] 的 useEffect。一旦檢索到該資訊并將其發回,您的資訊將保持最新狀態,但如果您需要將其存盤以備后用,則需要構建一個函式來保存該資料。
默認值:
const [name, setName] = useState(selectedApp.name ?? "Your default value here");
const [description, setDescription] = useState(selectedApp.description ?? "Your default value here");
加載圖示:
{selectedApp ? (
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
<TextField
className={classes.field}
onChange={(e) => setName(e.target.value)}
label="App Name"
variant="outlined"
color="secondary"
fullWidth
required
size="small"
defaultValue={selectedApp.name}
error={nameError}
/>
<TextField
className={classes.field}
onChange={(e) => setDescription(e.target.value)}
label="Description"
variant="outlined"
color="secondary"
rows={4}
fullWidth
required
size="small"
defaultValue={selectedApp.description}
error={descriptionError}
/>
<Grid container spacing={2}>
<Grid item>
<Button
// onClick={handleSubmit}
type="submit"
color="primary"
variant="contained"
endIcon={<SaveIcon />}
>
Save
</Button>
</Grid>
</Grid>
</form>
) : <LoadingIconComponent/>}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/454837.html
標籤:javascript 反应 异步等待 axios
上一篇:如何將前置加載div居中?
