React表单在重新渲染后不显示默认值。

huangapple go评论59阅读模式
英文:

React form not showing default values after rerender

问题

I have a scenario where my react-hook-form is not loading default values. These default values become available after a localStorage check that occurs inside a UseEffect() resulting in a state change to set the default values (unuploadedShoeData). However, this is not reflected in the form on rerender.

这里有一个情况,我的 react-hook-form 不加载默认值。这些默认值在 UseEffect() 内部进行本地存储检查后变为可用,导致状态更改以设置默认值(unuploadedShoeData)。然而,在重新渲染表单时没有反映出来。

The form definitely works for default values as if the default values are available prior to the initial form render (such as by hard coding the values) then these can be seen in the form when first rendered. In addition, I am logging unuploadedShoeData and can see that it is being set correctly. It seems like the form isn't rerendering for some reason.

这个表单对于默认值确实有效,如果默认值在初始表单渲染之前可用(比如通过硬编码这些值),那么在首次渲染时可以在表单中看到这些值。此外,我正在记录 unuploadedShoeData 并可以看到它被正确设置。似乎表单出于某种原因没有重新渲染。

Here is the code:

以下是代码:

const ShoeUpload = ({
  edit = false,
  user,
  setShoes,
  shoeOptions,
  api,
  shoes,
}) => {
  // ... 省略了部分代码 ...

  useEffect(() => {
    const shoeData = localStorage.getItem(UNUPLOADED_SHOE_DATA_KEY);
    if (shoeData) {
      setUnuploadedShoeData(JSON.parse(shoeData));
    }
  }, []);

  // ... 省略了部分代码 ...

  return (
    <div>
      {loading ? (
        <Grid
          container
          justifyContent="center"
          alignItems="center"
          direction="column"
          minHeight="80vh"
        >
          <Grid item xs={12} my={2}>
            <Typography variant="body1">Just a second...</Typography>
          </Grid>
          <Grid item xs={12}>
            <CircularProgress />
          </Grid>
        </Grid>
      ) : (
        <Box container className={classes.container}>
          <Card variant="outlined" className={classes.card}>
            <CardContent>
              <Typography variant="h6" component="h1" textAlign="center" mb={2}>
                {edit ? "Edit shoe" : "Upload a shoe to sell"}
              </Typography>
              <Form
                fields={fields}
                onSubmit={edit ? editShoe : uploadShoe}
                submitButtonText={edit ? "Update" : "Sell"}
              />
            </CardContent>
          </Card>
        </Box>
      )}
    </div>
  );
};

export default ShoeUpload;

I hope this helps with your code translation. Let me know if you need further assistance!

英文:

I have a scenario where my react-hook-form is not loading default values. These default values become available after a localStorage check that occurs inside a UseEffect() resulting in a state change to set the default values (unuploadedShoeData). However, this is not reflected in the form on rerender.

The form definitely works for default values as if the default values are available prior to the initial form render (such as by hard coding the values) then these can be seen in the form when first rendered. In addition, I am logging unuploadedShoeData and can see that it is being set correcty. It seem's like the form isn't rerendering for some reason.

Here is the code:

> const ShoeUpload = ({
> edit = false,
> user,
> setShoes,
> shoeOptions,
> api,
> shoes,
> }) => {
> const classes = useStyles();
> const navigate = useNavigate();
> const { id } = useParams();
> const [loading, setLoading] = useState(false);
> const [unuploadedShoeData, setUnuploadedShoeData] = useState(null);
>
> const UNUPLOADED_SHOE_DATA_KEY = "unuploadedShoeData";
>
> const shoe = edit
> ? shoes.filter((shoe) => shoe.id === parseInt(id)).pop()
> : unuploadedShoeData ?? null;
>
> console.log("shoe", shoe);
>
> useEffect(() => {
> const shoeData = >localStorage.getItem(UNUPLOADED_SHOE_DATA_KEY);
> if (shoeData) {
> setUnuploadedShoeData(JSON.parse(shoeData));
> }
> }, []);
>
> const _storeUnuploadedShoeData = (shoeData) => {
> const toStore = {
> brand: shoeData.brand.value,
> condition: shoeData.condition,
> foot: shoeData.foot.value,
> gender: shoeData.gender.value,
> icon: shoeData.icon,
> images: shoeData.images,
> price: shoeData.price,
> size: shoeData.size.value,
> };
> localStorage.setItem(UNUPLOADED_SHOE_DATA_KEY, JSON.stringify(toStore));
> };
>
> const uploadShoe = (data) => {>
> if (unuploadedShoeData) {
> localStorage.removeItem(UNUPLOADED_SHOE_DATA_KEY);
> }
>
> setLoading(true);
> api
> .createShoe(
> user.id,
> data.brand.value,
> data.icon,
> data.foot.value,
> data.gender.value,
> data.size.value,
> data.condition,
> data.price,
> data.images
> )
> .then((shoe) => {
> setLoading(false);
> setShoes((prevShoes) => [...prevShoes, shoe]);
> Analytics.uploadShoe(shoe);
> navigate(/shoes/${shoe.id});
> });
> };
>
> const editShoe = (data) => {
> setLoading(true);
> api
> .editShoe(
> shoe.id,
> data.brand.value,
> data.icon,
> data.foot.value,
> data.gender.value,
> data.size.value,
> data.condition,
> data.price,
> data.images,
> shoe.images
> )
> .then((shoe) => {
> setShoes((prevShoes) =>
> prevShoes.map((prevShoe) =>
> prevShoe.id === shoe.id ? shoe : prevShoe
> )
> );
> setLoading(false);
> navigate(/shoes/${shoe.id});
> });
> };
>
> const fields = [
> {
> name: "brand",
> label: "Shoe Brand",
> required: true,
> component: "autocomplete",
> options: shoeOptions?.brand,
> initial: shoe
> ? shoeOptions?.brand
> ?.filter((brand) => brand.value === shoe.brand)
> .pop()
> : null,
> },
> {
> name: "icon",
> label: "Shoe Icon",
> required: true,
> initial: shoe ? shoe.icon : null,
> },
> {
> name: "foot",
> label: "Foot",
> required: true,
> component: "autocomplete",
> options: shoeOptions?.foot,
> initial: shoe
> ? shoeOptions?.foot?.filter((foot) => foot.value === shoe.foot).pop()
> : null,
> },
> {
> name: "gender",
> label: "Gender",
> required: true,
> component: "autocomplete",
> options: shoeOptions?.gender,
> initial: shoe
> ? shoeOptions?.gender
> ?.filter((gender) => gender.value === shoe.gender)
> .pop()
> : null,
> },
> {
> name: "size",
> label: "Size (UK)",
> required: true,
> component: "autocomplete",
> options: shoeOptions?.size,
> initial: shoe
> ? shoeOptions?.size?.filter((size) => size.value === shoe.size).pop()
> : null,
> },
> {
> name: "price",
> label: "Price (£)",
> required: true,
> type: "number",
> initial: shoe ? shoe.price : null,
> },
> {
> name: "condition",
> label: "Condition",
> required: true,
> multiline: true,
> initial: shoe ? shoe.condition : null,
> },
> {
> name: "images",
> label: "Images",
> required: true,
> component: "imageUpload",
> acceptedFiles: ["image/jpeg", "image/png"],
> filesLimit: 6,
> initial: shoe ? shoe.images?.map((image) => image.image) : null,
> },
> ];
>
> return (
> <div>
> {loading ? (
> <Grid
> container
> justifyContent="center"
> alignItems="center"
> direction="column"
> minHeight="80vh"
> >
> <Grid item xs={12} my={2}>
> <Typography variant="body1">Just a second...</Typography>
> </Grid>
> <Grid item xs={12}>
> <CircularProgress />
> </Grid>
> </Grid>
> ) : (
> <Box container className={classes.container}>
> <Card variant="outlined" className={classes.card}>
> <CardContent>
> <Typography variant="h6" component="h1" textAlign="center" mb={2}>
> {edit ? "Edit shoe" : "Upload a shoe to sell"}
> </Typography>
> <Form
> fields={fields}
> onSubmit={edit ? editShoe : uploadShoe}
> submitButtonText={edit ? "Update" : "Sell"}
> />
> </CardContent>
> </Card>
> </Box>
> )}
> </div>
> );
> };
>
> export default ShoeUpload;

答案1

得分: 1

尝试添加一些console.log语句,比如对于shoeData,看看数据是否符合你的预期。这可能是因为数据是意外的或根本没有数据。但更多信息会有所帮助,比如组件返回什么以及它如何操作ShoeData。

英文:

Try to put some console.log statements like for shoeData and see if the data is what you really expect. This is probably cause the data is something unexpected or there is not any at all. It would help to see more though, like what the component is returning and how it is manipulating the ShoeData.

huangapple
  • 本文由 发表于 2023年6月6日 07:12:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76410527.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定