我正在使用Formik和Yup进行表单验证,
我在表单中使用了自定义表单字段(Algolia instant search),但无法验证
我尝试了2个选项,我认为选项2很有前途,但是有问题。
选项1:
如下所示,我尝试将自定义表单字段(<AlgoliaSearch />
)包装在表单项中,就像我对移动电话号码字段所做的那样,以实现类似的验证。事实证明,它不起作用,即使在填写该字段时也会显示错误消息。
选项2:
当用户在自定义表单字段(<AlgoliaSearch />
中设置值时,我在标准输入字段中设置了相同的值(在下面的代码中查找STANDARD INPUT FIELD),当我单击Submit时,formik不会确认字段(STANDARD INPUT FIELD)已填写(尽管已通过编程方式填写)。这可能是因为formik假定,由于尚未触摸该字段,因此尚未填充该字段。要解决此问题,我需要知道如何以编程方式设置使用Formik触摸过该字段。
在form.js中
const [selectedValue, setSelectedValue] = React.useState('');
const handleSearchValue = _selectedVlue => {
console.log(_selectedValue);
setSelectedValue(_selectedValue);
};
const validationSchema = Yup.object({
mobileNumber: Yup.string()
.required()
.min(10)
.label('Mobile number'),
searchValue: Yup.string()
.required()
.label('Search value'),
selectedValue: Yup.string()
.required()
.label('Selected value')
return (
<>
<Formik
initialValues={{
mobileNumber: '',
searchValue: '',
selectedValue:''
}}
onSubmit={handleSubmit}
validationSchema={validationSchema}
setFieldTouched={('selectedDoctor', true, true)}
>
<Form style={{ maxWidth: '250px', margin: '50px' }}>
<Form.Item name="mobileNumber" hasFeedback={true} showValidateSuccess={true}>
<Text>Mobile number</Text>
<Input
size="large"
name="mobileNumber"
/>
</Form.Item>
{/* CUSTOM FORM FIELD */}
<Form.Item name="searchValue" hasFeedback={true} showValidateSuccess={true}>
<AlgoliaSearch searchValue={handleSearchValue} />
</Form.Item>
{/* STANDARD INPUT FIELD */}
<Form.Item name="selectedValue" hasFeedback={true} showValidateSuccess={true}>
<Input name="selectedValue" value={selectedValue} user />
</Form.Item
</Form>
</Formik>
</>
);
AlgoliaSearch.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import algoliasearch from 'algoliasearch/lite';
import { InstantSearch, Configure, Hits, Highlight, connectSearchBox } from 'react-instantsearch-dom';
import Autocomplete from './Autocomplete';
import './Algolia.css';
// References
// Github, Autocomplete code: https://github.com/algolia/doc-code-samples/tree/master/React%20InstantSearch/autocomplete-results-page/src
// Algolia, autocomplete explained: https://www.algolia.com/doc/guides/building-search-ui/resources/ui-and-ux-patterns/in-depth/autocomplete/react/#overview
//const VirtalSearchBox = connectSearchBox(() => null);
const searchClient = algoliasearch('B1G2GM9NG0', 'aadef574be1f9252bb48d4ea09b5cfe5');
class AlgoliaSearch extends Component {
state = {
query: '',
};
onSuggestionSelected = (_, { suggestion }) => {
this.setState({
query: suggestion.name,
});
console.log('Setting suggestion.name: ' + suggestion.name);
this.props.searchValue(suggestion.name);
};
onSuggestionCleared = () => {
this.setState({
query: '',
});
};
render() {
const { query } = this.state;
return (
<div>
{/* <h1>React InstantSearch - Results page with autocomplete</h1> */}
<InstantSearch indexName="demo_ecommerce" searchClient={searchClient}>
<Configure hitsPerPage={3} />
<Autocomplete
onSuggestionSelected={this.onSuggestionSelected}
onSuggestionCleared={this.onSuggestionCleared}
/>
</InstantSearch>
</div>
);
}
}
function Hit(props) {
return (
<div>
<Highlight attribute="name" hit={props.hit} />
</div>
);
}
Hit.propTypes = {
hit: PropTypes.object.isRequired,
};
export default AlgoliaSearch;
在Autocomplete.js中
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Highlight, connectAutoComplete } from 'react-instantsearch-dom';
import AutoSuggest from 'react-autosuggest';
class AutoComplete extends Component {
static propTypes = {
hits: PropTypes.arrayOf(PropTypes.object).isRequired,
currentRefinement: PropTypes.string.isRequired,
refine: PropTypes.func.isRequired,
onSuggestionSelected: PropTypes.func.isRequired,
onSuggestionCleared: PropTypes.func.isRequired,
};
state = {
value: this.props.currentRefinement,
};
onChange = (_, { newValue }) => {
if (!newValue) {
this.props.onSuggestionCleared();
}
this.setState({
value: newValue,
});
};
onSuggestionsFetchRequested = ({ value }) => {
this.props.refine(value);
};
onSuggestionsClearRequested = () => {
this.props.refine();
};
getSuggestionValue(hit) {
return hit.name;
}
renderSuggestion(hit) {
return <Highlight attribute="name" hit={hit} tagName="mark" />;
}
render() {
const { hits, onSuggestionSelected } = this.props;
const { value } = this.state;
const inputProps = {
placeholder: 'Search for a doctor...',
onChange: this.onChange,
value,
};
return (
<AutoSuggest
suggestions={hits}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
onSuggestionSelected={onSuggestionSelected}
getSuggestionValue={this.getSuggestionValue}
renderSuggestion={this.renderSuggestion}
inputProps={inputProps}
name="selectedDoctor"
/>
);
}
}
export default connectAutoComplete(AutoComplete);