与Material UI <TextField />一起使用时,将'label'道具传递给Formik <Field />

时间:2020-06-12 09:27:15

标签: javascript reactjs material-ui formik formik-material-ui

我正在使用Formik和Material UI构建表单。

我通过以下方式利用Formik组件:

我的输入组件:

const Input = ({ field, form: { errors } }) => {
  const errorMessage = getIn(errors, field.name);
  return <TextField {...field} />;
};

然后进入我呈现的表单,这是我的操作方法:

<Field
  component={Input}
  name={`patients[${index}].firstName`}
/>

问题是Material UI使用标签属性在输入字段上显示标签,因此标签应该是传递给的属性。 如果我将其“硬编码”到我的“输入”组件中,它将无法使用可重复使用的comp。

因此可行,但不方便:

const Input = ({ field, form: { errors } }) => {
  console.log(field.label);
  const errorMessage = getIn(errors, field.name);
  return <TextField {...field} label="first name" />;
};

我希望在上面这样使用它:

<Field
  component={Input}
  name={`patients[${index}].firstName`}
  label="first name"
/>

但是上面的方法不能作为“标签”使用,Formik不能将其识别为道具(或者这就是我的理解,但是我可能是错的)。

有人遇到过这个问题吗?

我知道我可以使用“ name”值作为标签,但是它并不是很好的UX,因为它会给我留下诸如“ Patients [0] .firstName” aha这样的标签

2 个答案:

答案 0 :(得分:1)

这是一个很好的解决方案,本质上是您的解决方案,但您可以提供任何内容,而不仅仅是标签。 创建字段并将标签放在像这样:

<Field name={`patients[${index}].firstName`} label='First Name' component={MuiTextFieldFormik} />

诀窍是使用扩展运算符,然后自定义组件变为:

import React from 'react';
import { TextField } from "@material-ui/core"
import { get } from "lodash"

export const MuiTextFieldFormik = ({ field, form: { touched, errors }, ...props }) => {
  const error = get(touched, field.name) && !!get(errors, field.name)
  const helperText = get(touched, field.name) && get(errors, field.name)

  return (
    <TextField fullWidth variant="outlined" {...field} {...props} error={error} helperText={helperText} />
  )
}

令人失望的是他们的文档没有这么简单的例子

答案 1 :(得分:0)

好的,我想我找到了解决方案。我破坏参数的方式是,我只传递了字段和表单,这些字段和表单保存了大部分数据,因此以这种方式传递标签prop可以解决以下问题:

 import 'package:flutter/material.dart'; import
 'package:speech_recognition/speech_recognition.dart';

 void main() => runApp(MyApp());

 class MyApp extends StatelessWidget {   @override   Widget
 build(BuildContext context) {
     return MaterialApp(
       home: VoiceHome(),
     );   } }

 class VoiceHome extends StatefulWidget {   @override   _VoiceHomeState
 createState() => _VoiceHomeState(); }

 class _VoiceHomeState extends State<VoiceHome> {   SpeechRecognition
 _speechRecognition;   bool _isAvailable = false;   bool _isListening = false;

   String resultText = "";

   @override   void initState() {
     super.initState();
     initSpeechRecognizer();   }

   void initSpeechRecognizer() {
     _speechRecognition = SpeechRecognition();

     _speechRecognition.setAvailabilityHandler(
           (bool result) => setState(() => _isAvailable = result),
     );

     _speechRecognition.setRecognitionStartedHandler(
           () => setState(() => _isListening = true),
     );

     _speechRecognition.setRecognitionResultHandler(
           (String speech) => setState(() => resultText = speech),
     );

     _speechRecognition.setRecognitionCompleteHandler(
           () => setState(() => _isListening = false),
     );

     _speechRecognition.activate().then(
           (result) => setState(() => _isAvailable = result),
     );   }

   @override   Widget build(BuildContext context) {
     return Scaffold(
       body: Container(
         child: Column(
           mainAxisAlignment: MainAxisAlignment.center,
           crossAxisAlignment: CrossAxisAlignment.center,
           children: <Widget>[
             Row(
               mainAxisAlignment: MainAxisAlignment.center,
               children: <Widget>[
                 FloatingActionButton(
                   child: Icon(Icons.cancel),
                   mini: true,
                   backgroundColor: Colors.deepOrange,
                   onPressed: () {
                     if (_isListening)
                       _speechRecognition.cancel().then(
                             (result) => setState(() {
                           _isListening = result;
                           resultText = "";
                         }),
                       );
                   },
                 ),
                 FloatingActionButton(
                   child: Icon(Icons.mic),
                   onPressed: () {
                     if (_isAvailable && !_isListening)
                       _speechRecognition
                           .listen(locale: "en_US")
                           .then((result) => print('$result'));
                   },
                   backgroundColor: Colors.pink,
                 ),
                 FloatingActionButton(
                   child: Icon(Icons.stop),
                   mini: true,
                   backgroundColor: Colors.deepPurple,
                   onPressed: () {
                     if (_isListening)
                       _speechRecognition.stop().then(
                             (result) => setState(() => _isListening = result),
                       );
                   },
                 ),
               ],
             ),
             Container(
               width: MediaQuery.of(context).size.width * 0.8,
               decoration: BoxDecoration(
                 color: Colors.cyanAccent[100],
                 borderRadius: BorderRadius.circular(6.0),
               ),
               padding: EdgeInsets.symmetric(
                 vertical: 8.0,
                 horizontal: 12.0,
               ),
               child: Text(
                 resultText,
                 style: TextStyle(fontSize: 24.0),
               ),
             )
           ],
         ),
       ),
     );   } }

然后,当我以这种方式使用Formik组件时,将传递正确的标签:

const Input = ({ field, label, form: { errors } }) => {
  const errorMessage = getIn(errors, field.name);
  return <TextField {...field} label={label} />;
};