Formik Material UI React - Autocomplete - 未受控状态转为受控状态

29 浏览
0 Comments

Formik Material UI React - Autocomplete - 未受控状态转为受控状态

我正在试图弄清楚如何按照这里 Formik、Material UI和React工具的文档中的指示来使用自动完成字段。

文档中给出的示例是:

import { Autocomplete } from 'formik-material-ui-lab';
const options = [{ title: 'The Shawshank Redemption', year: 1994 }, ...]
 option.title}
  style={{ width: 300 }}
  renderInput={(params: AutocompleteRenderInputParams) => (
    
  )}
/>;

这里没有给出在getOptionLabel中使用Movie的含义提示。当我尝试使用这个时,Movie和renderInput对象中的AutocompleteRenderInputParams都被加下划线。我不知道为什么。

我看到了这个帖子,它尝试了另一种方法,但我也无法让它工作。

我有一个表单,有两个Autocomplete字段。当前,它看起来像这样。

当我尝试使用表单时,提交按钮会挂起,控制台日志会显示:

Material-UI:Autocomplete的getOptionLabel方法返回了一个未定义而非字符串的“”。

import React, { useState } from 'react';
import { Link  } from 'react-router-dom';
import firebase, {firestore} from '../../../firebase';
import { withStyles } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import Box from '@material-ui/core/Box';
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
import {
  Formik, Form, Field, ErrorMessage,
} from 'formik';
import * as Yup from 'yup';
import { Autocomplete, ToggleButtonGroup } from 'formik-material-ui-lab';
import { Switch } from 'formik-material-ui';
const styles = {
};
const allCategories = [
    {value: 'culture', label: 'Culture'},
    {value: 'other', label: 'Other'},
];
const sharingOptions = [
    {value: 'open', label: 'Openly'},
    {value: 'me', label: 'Only me'},
];
function Contact(props) {
  const { classes } = props;
  const [open, setOpen] = useState(false);
  const [isSubmitionCompleted, setSubmitionCompleted] = useState(false);
  function handleClose() {
    setOpen(false);
  }
  function handleClickOpen() {
    setSubmitionCompleted(false);
    setOpen(true);
  }
  return (
    
        

 

{!isSubmitionCompleted && Create an Impact Metric test form. { setSubmitting(true); firestore.collection("testing").doc().set({ values, createdAt: firebase.firestore.FieldValue.serverTimestamp() }) .then(() => { setSubmitionCompleted(true); }); }} validationSchema={Yup.object().shape({ title: Yup.string() .required('Required'), category: Yup.string() .required('Required'), sharing: Yup.string() .required('Required') })} > {(props) => { const { values, touched, errors, dirty, isSubmitting, handleChange, handleBlur, handleSubmit, handleReset, } = props; return (

option.label} style={{ width: 300 }} renderInput={(params: AutocompleteRenderInputParams) => ( )} /> option.label} style={{ width: 300 }} renderInput={(params: AutocompleteRenderInputParams) => ( )} /> {/* */}

); }}

} {isSubmitionCompleted && Thanks! test {/* */} }

 

    
  );
}
export default withStyles(styles)(Contact);

有没有人能看出如何在遵循上面链接中发布的文档的情况下使用表单、Material UI和Formik使自动完成功能工作?

我还尝试使用常规选择表单输入。这是表单字段:

                        
                          {allCategories.map(option => (
                            
                              {option.label}
                            
                          ))}
                        

当我尝试这样做时,控制台会出现警告,说:

instrument.ts:129 Material-UI: You have provided an out-of-range value `undefined` for the select component.
Consider providing a value that matches one of the available options or ''

这个警告毫无意义-表单正确填充了菜单。

我还得到一个错误,说:

index.js:1 警告:一个组件正在将一个未受控制的、类型未定义的输入变为受控制的。输入元素不应从未受控制的状态切换到受控制的状态(或反之亦然)。在组件的整个生命周期中,决定使用受控制的或未受控制的输入元素。更多信息

关于这个错误,我看到了这篇文章,它建议使用value(而不是input,我也这样做了)并将所有初始值定义为类型。对我来说,它们全都是字符串,虽然我试图用空数组替换选择字段。在这两种选择中,控制台都返回了相同的错误消息。

目前为止,我不在乎我使用自动完成还是选择器,我只想让它们中的一个运行。

有趣的是,在两种情况下(使用选择和自动完成),控制台都会记录警告,说:

Material-UI: You have provided an out-of-range value `undefined` for the select component.
Consider providing a value that matches one of the available options or ''.
The available values are `one`, `two`.
(anonymous) @ 0.chunk.js:141301
0.chunk.js:141301 Material-UI: You have provided an out-of-range value `undefined` for the select component.
Consider providing a value that matches one of the available options or ''.
The available values are `a`, `b`, `c`, `d`.

但是,只有一种错误的实例会报告如下:

 A component is changing an uncontrolled input of type undefined to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: react-website -controlled-components
    in input (created by ForwardRef(SelectInput))
    in ForwardRef(SelectInput) (created by ForwardRef(InputBase))
    in div (created by ForwardRef(InputBase))
    in ForwardRef(InputBase) (created by WithStyles(ForwardRef(InputBase)))
    in Wi

此错误指向类别选择表单输入。

我还尝试将来自此代码沙盒的性别选择表单字段添加到我的表单中,以查看是否可以让此项工作。当我注释掉上面描述的类别和共享字段,并添加一个默认值为空字符串的性别字段时,表单就会加载。

该字段为:


性别的选择字段出现,但非常窄,选项菜单不会填充选项,我无法选择任何内容。但是,表单确实会将空字符串保存在性别字段中。这是进展,但不足以继续前进。

同样的代码沙盒显示了一个使用自动完成的字段。我尝试将其调整并按如下方式在我的表单中使用:


当我尝试这样做时,出现了一个错误消息:

TypeError:renderInput不是一个函数

对我来说,这个错误消息没有意义,因为我在表单中没有使用renderInput。

当我尝试:

                        
                          {allCategories.map(option => (
                            
                              {option.label}
                            
                          ))}
                        
                      

我没有收到任何错误消息,并且可以保存带有选项详细信息的表单。然而,这并没有真正解决Autocomplete无法工作的问题。这也没有使用所示的Select字段链接文档。因此,我对为什么这个可以起作用或者为什么文档中所示的方法不起作用也不太清楚。

下一次尝试

使用这个codesandbox中的自动完成示例作为指南,我尝试:

 option.title}
              style={{width: 300}}
              renderInput={(params: AutocompleteRenderInputParams) => (
                
              )}
            />

与早期的示例一样,我的代码编辑器在getOptionLabel中出现的“any”值和AutocompleteRenderInputParams处下划线。我找不到任何解释表单字段这些元素意味着什么或做什么的文档。无论如何,我已经按照代码沙盒中所示导入了AutocompleteRenderInputParams。

我将表单中自动完成字段的初始值设置为空数组,尽管我注意到代码沙箱在此示例中没有设置初始值。当我尝试删除自动完成的初始值时,会产生与当初始值为空数组时生成的相同的错误,但我还会在控制台中收到一个警告,提示:

警告:autocomplete的值不是一个数组,这可能会导致意外行为。

当我尝试这段代码时,我的控制台会记录以下错误:

TypeError: Cannot read property \'toLowerCase\' of undefined

Material-UI: Autocomplete的getOptionLabel方法返回了undefined而不是{\"value\":\"open\",\"label\":\"Open\"}的字符串。

admin 更改状态以发布 2023年5月24日
0
0 Comments

对于那些卡住了的人,这个方法可以 - 尽管我不明白为什么。上面帖子中指出的下划线错误仍然存在,我不知道该如何解决。

分享这个作为一个向前的方式 - 而不是一个好的解决方案。

import React, { useState } from 'react';
import {render} from 'react-dom';
import { Link  } from 'react-router-dom';
import firebase, {firestore} from '../../../../firebase';
import { withStyles } from '@material-ui/core/styles';
import {
  Button,
  LinearProgress,
  MenuItem,
  FormControl,
  InputLabel,
  FormControlLabel,
  TextField,
  Typography,
  Box,
  Grid,
  Checkbox,
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
} from '@material-ui/core';
import MuiTextField from '@material-ui/core/TextField';
import ToggleButton from '@material-ui/lab/ToggleButton';
import FormatAlignLeftIcon from '@material-ui/icons/FormatAlignLeft';
import FormatAlignCenterIcon from '@material-ui/icons/FormatAlignCenter';
import FormatAlignRightIcon from '@material-ui/icons/FormatAlignRight';
import FormatAlignJustifyIcon from '@material-ui/icons/FormatAlignJustify';
import {
  Formik, Form, Field, ErrorMessage,
} from 'formik';
import * as Yup from 'yup';
// import { Autocomplete, ToggleButtonGroup } from 'formik-material-ui-lab';
import {
  Autocomplete,
  ToggleButtonGroup,
  AutocompleteRenderInputParams,
} from 'formik-material-ui-lab';
import {
  fieldToTextField,
  TextFieldProps,
  Select,
  Switch,
} from 'formik-material-ui';
const allCategories = [
    {value: 'one', label: 'Col'},
    {value: 'two', label: 'Com'},
];
function UpperCasingTextField(props: TextFieldProps) {
  const {
    form: {setFieldValue},
    field: {name},
  } = props;
  const onChange = React.useCallback(
    event => {
      const {value} = event.target;
      setFieldValue(name, value ? value.toUpperCase() : '');
    },
    [setFieldValue, name]
  );
  return ;
}
function Glossary(props) {
  const { classes } = props;
  const [open, setOpen] = useState(false);
  const [isSubmitionCompleted, setSubmitionCompleted] = useState(false);
  function handleClose() {
    setOpen(false);
  }
  function handleClickOpen() {
    setSubmitionCompleted(false);
    setOpen(true);
  }
  return (
    
        
      
        {!isSubmitionCompleted &&
          
            Create 
            
              
              
               {
                   setSubmitting(true);
                   firestore.collection("glossary").doc().set({
                    ...values,
                    createdAt: firebase.firestore.FieldValue.serverTimestamp()
                })
                  .then(() => {
                    setSubmitionCompleted(true);
                  });
                }}
                validationSchema={Yup.object().shape({
                  term: Yup.string()
                    .required('Required'),
                  definition: Yup.string()
                    .required('Required'),
                  category: Yup.string()
                    .required('Required'),
                  attribution: Yup.boolean()
                    .required('Required'),
                  context: Yup.string()
                    .required("Required"),
                })}
              >
                {(props) => {
                  const {
                    values,
                    touched,
                    errors,
                    dirty,
                    isSubmitting,
                    handleChange,
                    handleBlur,
                    handleSubmit,
                    handleReset,
                  } = props;
                  return (
                    
Choose)? Attribution Anonymous option.label} style={{width: 300}} renderInput={(params: AutocompleteRenderInputParams) => ( )} /> {/* */} ); }}
} {isSubmitionCompleted && Thanks! Thank you {/* */} }
); } export default withStyles(styles)(Glossary);

0
0 Comments

工作实例:

演示

import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import { Formik, Field } from "formik";
import { Autocomplete } from "formik-material-ui-lab";
import { TextField } from "@material-ui/core";
const options = [
  { title: "The Shawshank Redemption", year: 1994 },
  { title: "Inglourious Basterds", year: 2009 },
  { title: "Snatch", year: 2000 },
  { title: "3 Idiots", year: 2009 },
  { title: "Monty Python and the Holy Grail", year: 1975 }
];
function App() {
  return (
    
      {() => (
         option.title}
          style={{ width: 300 }}
          renderInput={(params) => (
            
          )}
        />
      )}
    
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(, rootElement);

0