代码之家  ›  专栏  ›  技术社区  ›  Michael Coxon

React挂钩表单未填充提取的数据

  •  0
  • Michael Coxon  · 技术社区  · 2 年前

    我有一个表单,它是一组选项卡面板的一部分。表单本身看起来是这样的:

    import * as React from "react";
    import { useForm, SubmitHandler, Controller } from "react-hook-form";
    import { Char } from "../../models";
    import { strikerTheme } from "../../../shared/components/StrikerTheme";
    import ThemeProvider from "@mui/material/styles/ThemeProvider";
    import TextField from "@mui/material/TextField";
    import MenuItem from "@mui/material/MenuItem";
    import InputAdornment from "@mui/material/InputAdornment";
    import { useAppSelector } from "../../../../app/hooks";
    import { getTraits, getIdeals } from "../../../shared/specSlice";
    import { Quality } from "../../models/specs";
    import { CheckboxGroup } from ".";
    
    
    export const DescriptionForm = ({
      onSubmit,
      data
    }: {
      data: Partial<Char>;
      onSubmit: SubmitHandler<Partial<Char>>;
    }) => {
    
      const specState = useAppSelector(state => state.specState);
    
      console.log('imitial data')
      console.log(data)
      const { handleSubmit, control } = useForm({defaultValues: data});
    
      const alignments = ['Lawful Good', 'Neutral Good', 'Chaotic Good', 'Lawful Neutral', 'Neutral', 'Chaotic Neutral', 'Lawful Evil', 'Neutral Evil', 'Chaotic Evil']
      const traits: Quality[] = getTraits(specState.specKeys);
      const ideals: Quality[] = getIdeals(specState.specKeys);
    
    
      return data && (
    
        <ThemeProvider theme={strikerTheme}>
          <form className='form' onSubmit={handleSubmit(onSubmit)}>
            <h4>Description</h4>
            <div className='form-row'>
              <Controller name="name" control={control} render={({ field }) => <TextField sx={{ width: '40ch' }} {...field} label="character name" />} />
            </div>
            <div className='form-row'>
              <Controller name="experience" control={control} render={({ field }) => <TextField {...field} label="experience" />} />
              <Controller name="levels" control={control} render={({ field }) => <TextField {...field} label="level" />} />
            </div>
            <div className='form-row'>
              <Controller name="age" control={control} render={({ field }) => <TextField {...field} label="age" />} />
              <Controller name="gender" control={control} render={({ field }) => <TextField {...field} label="gender" />} />
              <Controller name="height" control={control} render={({ field }) => <TextField {...field} label="height" />} />
              <Controller name="weight" control={control} render={({ field }) =>
                <TextField {...field} label="weight" InputProps={{
                  endAdornment: <InputAdornment position="end">kg</InputAdornment>,
                }}
                />}
              />
            </div>
            <div className='form-row'>
              <Controller
                name="alignment"
                control={control}
                render={({ field }) => <TextField {...field} label="alignment" helperText="Please select your alignment" select>
                  {alignments.map((option) => (
                    <MenuItem key={option} value={option}>
                      {option}
                    </MenuItem>
                  ))}
                </TextField>}
              />
              <div className='form-row'>
                <Controller name="traits" control={control} render={({ field }) => <CheckboxGroup
                  control={control}
                  label="traits"
                  options={traits}
                  {...field}
                />
                } />
              </div>
    
              <div className='form-row'>
    
                <Controller name="ideals" control={control} render={({ field }) => <CheckboxGroup
                  control={control}
                  label="ideals"
                  options={ideals}
                  {...field}
                />
                } />
              </div>
    
            </div>
            <button
              type='submit'
              className='btn btn-block btn-danger'
            >
              Submit
            </button>
    
          </form>
        </ThemeProvider>
    
      )
    };
    
    

    请注意,console.log语句显示数据已完全填充,例如:

    enter image description here

    然而表单呈现为该数据为空(即未定义但具有初始化的默认值)。

    这个 onSubmit 实际上在父组件中,并且非常简单:

    const onSubmit = async (
        data: Partial<Char>
      ) => {
        if (charstate.char) {
          await dispatch(editChar(data));
        } else {
          // its a new char, so create 
    
          await dispatch(createChar(data));
        }
      };
    

    它是有效的,换句话说,我可以填写表单,表单被提交并保存到数据存储中。

    我尝试了多种方法,要么让表单等待值被填充,要么尝试强制控件读取值(取决于这是异步问题还是引用问题)。感觉我错过了一些简单的东西。

    我错过了什么?

    1 回复  |  直到 2 年前
        1
  •  1
  •   Roar S.    2 年前

    请尝试

    const { handleSubmit, control } = useForm(values: data);
    

    described in the docs

    值道具将对更改做出反应并更新表单值, 当您的表单需要由外部状态更新时,这很有用 或服务器数据。