我正在使用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这样的标签
答案 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} />;
};