React-Select是github上一个极其火的控件库,星数达到13004,它是React开发中几乎是你必需打交道的一个内容。React Select的基本功能实现的是一个表单中的常见的下拉列表框控件,其实它的功能扩展来看远远不止如此,它支持:
等等。
但是,如果在你的开发中使用的是一个很基础性的下拉列表框,那么你可以直接使用类似于Semantic UI或者是Material React控件库的Select组件,甚至是最基本的HTML5组件中的那个。
值得注意的是,如如今react-select组件从1.0升级到2.0,变化了巨大变化。有关细节请参考官方网站,总起来看越升级越容易使用,功能也越强大。
Formik官方也提供了一个使用react-select组件的基本例子,但是使用的是react-select组件的Ver 1.x。在1.x版本时期,组件的样式是使用css方案定义的,但是升级到2.0后,样式使用了更为先进且更迎合React开发思想的Emotion这个开源库(使用JSX组件思想——CSS-in-JS——开发样式)。由于Formik官方提供的相关实例极为简单,所以几需要作两处修改即可。
工程名称:formik-09x-react-select-example,主要文件:index.js
修改后完整代码如下:
import './formik-demo.css';
import React from 'react';
import { render } from 'react-dom';
import { withFormik } from 'formik';
//ERROR NOW: import Yup from 'yup';==>changed into the following
import * as Yup from 'yup';
import Select from 'react-select';
//NOT SUPPORTED IN VERSION 2.X.
// Styles are now implemented with css-in-js rather than less / scss stylesheets
//import 'react-select/dist/react-select.css';
// Helper styles for demo
import './formik-demo.css';
import {
MoreResources,
DisplayFormikState,
} from './formik-helper';
import SimpleSelect from './SimpleSelect'
import AnimatedMulti from './AnimationMultiSelect'
const formikEnhancer = withFormik({
mapPropsToValues: props => ({
email: '',
topics: []
}),
validationSchema: Yup.object().shape({
email: Yup.string()
.email('Invalid email address')
.required('Email is required!'),
topics: Yup.array()
.min(3, 'Pick at least 3 tags')
.of(
Yup.object().shape({
label: Yup.string().required(),
value: Yup.string().required(),
})
),
}),
handleSubmit: (values, { setSubmitting }) => {
const payload = {
...values,
topics: values.topics.map(t => t.value),
};
setTimeout(() => {
alert(JSON.stringify(payload, null, 2));
setSubmitting(false);
}, 1000);
},
displayName: 'MyForm'
});
const MyForm = props => {
const {
values,
touched,
dirty,
errors,
handleChange,
handleBlur,
handleSubmit,
handleReset,
setFieldValue,
setFieldTouched,
isSubmitting,
} = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email" style={{ display: 'block' }}>
Email
</label>
<input
id="email"
placeholder="Enter your email"
type="email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
/>
{errors.email &&
touched.email && (
<div style={{ color: 'red', marginTop: '.5rem' }}>
{errors.email}
</div>
)}
<MySelect
value={values.topics}
onChange={setFieldValue}
onBlur={setFieldTouched}
error={errors.topics}
touched={touched.topics}
/>
<button
type="button"
className="outline"
onClick={handleReset}
disabled={!dirty || isSubmitting}
>
Reset
</button>
<button type="submit" disabled={isSubmitting}>
Submit
</button>
<DisplayFormikState {...props} />
</form>
);
};
const options = [
{ value: 'Food', label: 'Food' },
{ value: 'Being Fabulous', label: 'Being Fabulous' },
{ value: 'Ken Wheeler', label: 'Ken Wheeler' },
{ value: 'ReasonML', label: 'ReasonML' },
{ value: 'Unicorns', label: 'Unicorns' },
{ value: 'Kittens', label: 'Kittens' },
];
class MySelect extends React.Component {
handleChange = value => {
// this is going to call setFieldValue and manually update values.topcis
this.props.onChange('topics', value);
};
handleBlur = () => {
// this is going to call setFieldTouched and manually update touched.topcis
this.props.onBlur('topics', true);
};
render() {
return (
<div style={{ margin: '1rem 0' }}>
<label htmlFor="color">
Topics (select at least 3){' '}
</label>
<Select
id="color"
options={options}
isMulti
onChange={this.handleChange}
onBlur={this.handleBlur}
value={this.props.value}
/>
{!!this.props.error &&
this.props.touched && (
<div style={{ color: 'red', marginTop: '.5rem' }}>
{this.props.error}
</div>
)}
</div>
);
}
}
const MyEnhancedForm = formikEnhancer(MyForm);
const App = () => (
<div className="app">
<h1>
Using{' '}
<a href="https://github.com/jaredpalmer/formik">
Formik
</a>{' '}
with 3rd-party input components
</h1>
<p>
This example shows to use Formik with a 3rd-party
input component. The trick is to use Formik's{' '}
<code>setFieldValue</code> prop and a custom component
class whenever you need a custom change handler.{' '}
</p>
<p>
To show this off, below is a Formik-enhanced form. It
has a "vanilla" Formik input for <code>email</code>{' '}
and a custom select component for <code>topics</code>{' '}
that uses Jed Watson's {' '}
<a href="https://github.com/JedWatson/react-select">
react-select
</a>{' '}
library.
</p>
<MyEnhancedForm />
<hr/>
<SimpleSelect/>
<hr/>
<AnimatedMulti/>
<hr/>
<MoreResources />
</div>
);
render(<App />, document.getElementById('root'));
第一处修改是屏蔽css文件的导入引用,如下:
//import 'react-select/dist/react-select.css';
第二处更为简单,只需要把<Select/>组件中的属性表达方式修改一下,即把multi={true}修改为isMulti就可以了,如下:
<Select
id="color"
options={options}
isMulti
onChange={this.handleChange}
onBlur={this.handleBlur}
value={this.props.value}
/>
另外还添加了两个我自己加入的react-select组件,分别是SimpleSelect和AnimationMultiSelect,它们各自的源码如下,请参考:
//SimpleSelect.js
import React,{Component} from 'react'
import Select from 'react-select'
const options=[
{value:'liu',label:'刘备'},
{value:'guan',label:'关羽'},
{value:'zhang',label:'张飞'}
]
const SimpleSelect=()=>(
<Select options={options}/>
)
export default SimpleSelect
//AnimationMultiSelect
import React from 'react';
import Select from 'react-select';
import makeAnimated from 'react-select/lib/animated';
// import { colourOptions } from '../data';
const colourOptions=[
{value:'c1',label:'刘备'},
{value:'c2',label:'关羽1'},
{value:'c3',label:'关羽2'},
{value:'c4',label:'关羽3'},
{value:'c5',label:'张飞'}
]
export default function AnimatedMulti() {
return (
<Select
closeMenuOnSelect={false}
components={makeAnimated()}
defaultValue={[colourOptions[4], colourOptions[5]]}
isMulti
options={colourOptions}
/>
);
}
1,https://react-select.com/home#getting-started
2,https://blog.csdn.net/Tony1590112/article/details/78296345
3,https://github.com/emotion-js/emotion
4,https://github.com/jaredpalmer/formik
转载于:https://blog.51cto.com/zhuxianzhong/2153433