Simple String Selector with Ant Design Mobile

Thu Apr 13 2023

Introduction

Ant Design Mobile provides a Picker component to select a value from a list. However, it is not easy to use it to select a string value.

In this post, I will create a SimpleStringSelector component with the Picker. It provides a simple way to select a string value from a list, it can fetch options asynchronously, and it is a Form.Item by default.

You can use it like this:

tsx
|
import React from 'react'; import { Form } from 'antd-mobile'; const Demo = () => { const [form] = Form.useForm(); return ( <Form form={form}> <SimpleStringSelector form={form} label="Name" formName="name" placeholder="Please select name" rules={[{ required: true, message: 'Please select name' }]} fetchOptions={async () => { // simulate a network request return ['name1', 'name2']; }} /> </Form> ); };

Code

tsx
|
import React from 'react'; import { Form, Picker, } from 'antd-mobile'; type SimpleStringSelectorProps = { label: string; formName: string; placeholder?: string; rules?: Rule[]; initialValue?: string; /** * fetch data asynchronously */ fetchOptions: () => Promise<string[]>; /** * form instance, it is used to reload initial value when changed */ form?: FormInstance; }; const SimpleStringSelector = ({ label, formName, placeholder, rules, initialValue, fetchOptions, form, }: SimpleStringSelectorProps) => { const [loading, setLoading] = useState(false); const [options, setOptions] = useState<{ label: string; value: string }[]>([]); const [visible, setVisible] = useState(false); const [value, setValue] = useState<string[] | undefined>() useEffect(() => { const _fetchOptions = async () => { if (loading) { return; } setLoading(true); try { const data = await fetchOptions(); const options = data.map((option) => ({ value: option, label: option, })); setOptions(options); } catch (e) { console.error(e); } setLoading(false); }; _fetchOptions().then(); }, [0]); // update initial value when it is changed useEffect(() => { if (initialValue) { form?.setFieldsValue({[formName]: value}) } }, [initialValue]); // prevent rendering while loading if (loading) { return <></>; } return ( <Form.Item name={formName} trigger='onConfirm' label={label} rules={rules} initialValue={initialValue ? [initialValue] : []} onClick={() => setVisible(true)} > <Picker columns={[options]} visible={visible} onClose={() => setVisible(false)} value={value} onConfirm={(v) => { setValue(v as string[]); }} > {(value) => { return value[0]?.value || placeholder || `Please select ${label}; }} </Picker> </Form.Item> ); };