Skip to content

Instantly share code, notes, and snippets.

@pjchender
Last active June 4, 2019 02:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pjchender/563c83e7281edfc09445e3d2e897d402 to your computer and use it in GitHub Desktop.
Save pjchender/563c83e7281edfc09445e3d2e897d402 to your computer and use it in GitHub Desktop.
Reat Formik
/* demo use for array of objects with formik */
import React from 'react';
import { Formik, Field, Form, FieldArray, ErrorMessage } from 'formik';
import Debug from './Debug';
// import * as Yup from 'yup';
// STEP 1: 定義 initialValues
const initialValues = {
friends: [
{
name: '',
email: '',
},
],
};
const Invitation = () => (
<div>
<h1>Invite Friends</h1>
{/* STEP 2:
將 Formik 把 Form 包起來
並帶入 `initialValues` 和 `onSubmit(<values>)*/}
<Formik
initialValues={initialValues}
onSubmit={(values) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
}, 500);
}}
>
{/* STEP 3: 把 form 用一個 function({values, isSubmitting}) 包起來*/}
{({ values, isSubmitting }) => (
<div>
<div className="row">
{/* STEP 6: 如果資料是 array of objects 可以使用 <FieldArray> */}
<Form className="col s-12">
<FieldArray name="friends">
{/* STEP 7: 在 FieldArray 中可以拿到 push 和 remove 的方法 */}
{({ push, remove }) => (
<>
{values.friends &&
values.friends.length > 0 &&
values.friends.map((value, index) => (
<div className="row">
<div className="col">
{/* STEP 4: 把 name 的名稱和 values 內的資料對應 */}
<Field name={`friends[${index}].name`} type="text">
{/* STEP 5-1: 有需要可以把屬性拿出來自己組 input */}
{({ field, form }) => (
<input
{...field}
type="text"
placeholder="Jane Doe"
/>
)}
</Field>
</div>
<div className="col">
{/* STEP 5-2: 或者直接用 Field 帶入需要的屬性 */}
<Field
name={`friends[${index}].email`}
type="email"
placeholder="jane@example.com"
/>
</div>
<div className="col">
<button type="button" onClick={() => remove(index)}>
X
</button>
</div>
</div>
))}
<button
type="button"
className="waves-effect waves-light btn-small"
onClick={() => push({ name: '', email: '' })}
>
Add Friend
</button>
</>
)}
</FieldArray>
<button
type="submit"
className="waves-effect waves-light btn-small w-100"
disabled={isSubmitting}
>
Submit
</button>
</Form>
</div>
<div className="col s-12">
<Debug />
</div>
</div>
)}
</Formik>
</div>
);
export default Invitation;
// STEP7: create onSubmit function as props passed into <Formik /> as a callback function after handleSubmit
import React from 'react';
class MiniFormik extends React.Component {
state = {
values: this.props.initialValues || {},
touched: {},
errors: {},
};
handleChange = (event) => {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState((prevState) => ({
values: {
...prevState.values,
[name]: value,
},
}));
};
handleBlur = (event) => {
const target = event.target;
const name = target.name;
this.setState((prevState) => ({
touched: {
...prevState.touched,
[name]: true,
},
}));
};
handleSubmit = (event) => {
const { onSubmit } = this.props;
const { values } = this.state;
event.preventDefault();
onSubmit(values);
};
render() {
const { children } = this.props;
return children({
...this.state,
handleChange: this.handleChange,
handleBlur: this.handleBlur,
handleSubmit: this.handleSubmit,
});
}
}
class Reservation extends React.Component {
render() {
return (
<MiniFormik
initialValues={{
isGoing: true,
numberOfGuests: 2,
}}
onSubmit={(values) => alert(JSON.stringify(values), null, 2)}
>
{({
values,
touched,
errors,
handleChange,
handleBlur,
handleSubmit,
}) => (
<form onSubmit={handleSubmit}>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={values.isGoing}
onChange={handleChange}
onBlur={handleBlur}
/>
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={values.numberOfGuests}
onChange={handleChange}
onBlur={handleBlur}
/>
</label>
<pre>
{JSON.stringify(
{
values,
touched,
errors,
},
null,
2
)}
</pre>
</form>
)}
</MiniFormik>
);
}
}
export default Reservation;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment