Skip to content

Instantly share code, notes, and snippets.

@benjaminparnell
Created August 20, 2018 22:29
Show Gist options
  • Save benjaminparnell/41a237d8cd0257107fd5a748d93b324d to your computer and use it in GitHub Desktop.
Save benjaminparnell/41a237d8cd0257107fd5a748d93b324d to your computer and use it in GitHub Desktop.
formik-addresses-test.tsx
import * as React from "react";
import { render } from "react-dom";
import {
Formik,
FieldArray,
Field,
Form,
FormikProps,
ArrayHelpers
} from "formik";
type Address = {
lineOne: string;
lineTwo: string;
city: string;
postcode: string;
};
// AddressForm has all logic for finding addresses etc. The validation schema for addresses
// can be defined in this file too. This component relies on being rendered inside
// a Formik component.
type AddressFormState = {
loading: boolean;
postcode: string;
};
class AddressForm extends React.Component<
{
setValues: (address: Address) => void;
path: string;
},
AddressFormState
> {
state: AddressFormState = {
loading: false,
postcode: ""
};
onPostcodeSearchChange(e: React.FormEvent<HTMLInputElement>) {
this.setState({
postcode: e.currentTarget.value
});
}
onSearchClicked() {
this.setState({ loading: true });
setTimeout(() => {
// This fills in the address at the given index with these details
this.props.setValues({
lineOne: "3 Villiers Road",
lineTwo: "West Bridgford",
city: "Nottingham",
postcode: "NG2 6FR"
});
this.setState({ loading: false });
}, 2000);
}
render() {
const path = this.props.path;
return (
<div>
<p>{path}</p>
<div>
<label>Enter your potcode</label>
<input
type="text"
name="postcodeSearch"
onChange={this.onPostcodeSearchChange.bind(this)}
/>
<button
type="button"
disabled={this.state.loading}
onClick={this.onSearchClicked.bind(this)}
>
Search
</button>
</div>
<Field name={`${path}.lineOne`} />
<Field name={`${path}.lineTwo`} />
<Field name={`${path}.city`} />
<Field name={`${path}.postcode`} />
</div>
);
}
}
// AddressesForm has all logic for listing input addresses and selecting
// whether to add more/edit. Could have its own state etc. Allows us to get
// all the noise of this complicated stuff out of the form itself.
const AddressesForm = ({
push,
form
}: ArrayHelpers & { form: FormikProps<FormValues> }) => (
<div>
{form.values.addresses.map((address, index) => (
<AddressForm
key={index}
setValues={form.setFieldValue.bind(form, `addresses.${index}`)}
path={`addresses.${index}`}
/>
))}
<button
type="button"
onClick={() =>
push({
lineOne: "",
lineTwo: "",
city: "",
postcode: ""
})
}
>
Add
</button>
</div>
);
// Root component containing the rest of the formik form
type FormValues = {
addresses: Address[];
};
class App extends React.Component {
render() {
return (
<div>
<h1>Formik test</h1>
<Formik
initialValues={{ addresses: [] }}
onSubmit={(values: FormValues) => console.log(values)}
render={({ isValid }: FormikProps<FormValues>) => (
<Form>
<FieldArray name="addresses" component={AddressesForm} />
<button type="submit" disabled={!isValid}>
Submit
</button>
</Form>
)}
/>
</div>
);
}
}
render(<App />, document.getElementById("root"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment