先日、 Typescript Deep Dive (日本語版) を読みました。react 経由で typescript に入ってきましたが、色々と追いついてなくてヤバイです。
それはそうと、formik + material-ui でググったら、material-ui をラップしたような formik-material-ui があったので、これを素振りしてみました。
素振り
今回は、HOC として Formik を食わせる withFormik
でやりました。
基本的には、formik
の Field
の component
に、
formik-material-ui
のコンポーネントを渡してあげればよさそうでした。
Textfield
以下の画像の項目は TextField を渡すだけでできました。
<Field
name="text"
label="text *"
type="text"
component={TextField}
value={values.text}
onChange={handleChange}
fullWidth={true}
/>
<br />
<Field
name="email"
label="email *"
type="email"
component={TextField}
value={values.email}
onChange={handleChange}
fullWidth={true}
/>
<br />
<Field
name="password"
label="password *"
type="password"
component={TextField}
value={values.password}
onChange={handleChange}
error={errors.password && touched.password}
fullWidth={true}
/>
<br />
<Field
name="textarea"
label="textarea *"
type="text"
component={TextField}
value={values.textarea}
multiline={true}
fullWidth={true}
/>
<br />
<Field
name="select"
label="select *"
select={true}
component={TextField}
variant="outlined"
InputLabelProps={{ shrink: true }}
>
{['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map((value, index) => (
<MenuItem key={index} value={value}>
{value}
</MenuItem>
))}
</Field>
<br />
<Field
name="date"
label="date *"
type="date"
InputLabelProps={{ shrink: true }}
component={TextField}
variant="outlined"
/>
<br />
ラジオ、チェックボックス系
<Field
name="gender"
label="gender *"
component={RadioGroup}
values={values.gender}
onChange={handleChange}
>
<FormControlLabel
value="male"
label="Male"
control={<Radio disabled={isSubmitting} />}
disabled={isSubmitting}
/>
<FormControlLabel
value="female"
label="Female"
control={<Radio disabled={isSubmitting} />}
disabled={isSubmitting}
/>
<FormControlLabel
value="other"
label="Other"
control={<Radio disabled={isSubmitting} />}
disabled={isSubmitting}
/>
</Field>
<br />
<Field name="switch" label="switch" component={Switch} />
<br />
<Field name="checkbox" label="checkbox" component={Checkbox} />
<br />
<Field
name="checkboxwithlabel"
label="checkboxwithlabel"
component={CheckboxWithLabel}
Label={{ label: 'checkbox with label' }}
/>
<br />
ファイルアップロード系
プレビュー付きとかをやろうとすると、面倒なのことになるので、
そういうときは素直に Dropzone
とかで片付けたほうがよさげです。
<Field component={SimpleFileUpload} name="upload_file" />
<br />
<Field
name="file"
type="file"
onChange={(e: any) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (item: any) => {
setFieldValue('file_data', item.target.result);
};
reader.readAsDataURL(file);
}}
/>
<DropzoneArea
onChange={acceptedFiles => {
setFieldValue('files', acceptedFiles);
acceptedFiles.map((f: any, index: number) => {
const reader = new FileReader();
reader.onload = (item: any) => {
setFieldValue(`files_data${index}`, item.target.result);
};
reader.readAsDataURL(f);
});
}}
/>
<br />
参考にしたドキュメント等
- jaredpalmer/formik
- stackworx/formik-material-ui
- react-dropzone/react-dropzone
- Yuvaleros/material-ui-dropzone
- oukayuka/UserSearchForm.tsx
- Formik — Handling files and reCaptcha
コード
いろいろ試して遊んでいたので、汚い dispatch 等々が入ってます。