Skip to content

Commit e1c8d42

Browse files
committed
feat(redux-form): add typings
1 parent ff1061d commit e1c8d42

3 files changed

Lines changed: 40 additions & 34 deletions

File tree

src/app/components/Form.tsx

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,31 @@
11
import * as React from "react";
2-
import { Field, reduxForm } from "redux-form";
3-
import { aol, email, maxLength, minValue, numberType, renderField, required, tooOld } from "../helpers/FormHelper";
2+
import { Field, FormProps, reduxForm } from "redux-form";
3+
import {
4+
aol, email, maxLength, minLength, minValue,
5+
numberType, renderField, required, tooOld
6+
} from "../helpers/FormHelper";
47

5-
class Form extends React.Component<any, any> {
8+
export interface IFormData {
9+
username: string;
10+
password: string;
11+
email: string;
12+
age: number;
13+
}
14+
15+
interface IProps {
16+
onSubmit: (values: IFormData) => Promise<any>;
17+
}
18+
19+
class Form extends React.Component<FormProps<IFormData, IProps, void> & IProps, void> {
620
public render(): JSX.Element {
721
const {handleSubmit, pristine, reset, submitting} = this.props;
822

923
return (
1024
<form onSubmit={handleSubmit}>
11-
<Field
12-
name="username"
13-
type="text"
14-
component={renderField}
15-
label="Username"
16-
validate={[required, maxLength(15)]}
17-
/>
18-
<Field
19-
name="email"
20-
type="email"
21-
component={renderField}
22-
label="Email"
23-
validate={email}
24-
warn={aol}
25-
/>
26-
<Field
27-
name="age"
28-
type="number"
29-
component={renderField}
30-
label="Age"
31-
validate={[required, numberType, minValue(18)]}
32-
warn={tooOld}
33-
/>
25+
<Field name="username" type="text" component={renderField} label="Username" validate={[required, maxLength(15)]}/>
26+
<Field name="password" type="password" component={renderField} label="Password" validate={[required, minLength(8)]}/>
27+
<Field name="email" type="email" component={renderField} label="Email" validate={email} warn={aol}/>
28+
<Field name="age" type="number" component={renderField} label="Age" validate={[required, numberType, minValue(18)]} warn={tooOld}/>
3429
<div>
3530
<button type="submit" disabled={submitting}>Submit</button>
3631
<button type="button" disabled={pristine || submitting} onClick={reset}>

src/app/containers/FormPage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import {Promise} from "es6-promise";
22
import * as React from "react";
33
import {Form} from "../components";
4+
import {IFormData} from "../components/Form";
45

56
class FormPage extends React.Component<void, void> {
67
constructor() {
78
super();
89
this.showResults = this.showResults.bind(this);
910
}
10-
public showResults(values: any): Promise<any> {
11+
public showResults(values: IFormData): Promise<any> {
1112
return new Promise((resolve) => {
1213
setTimeout(
1314
() => {

src/app/helpers/FormHelper.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
import * as React from "react";
2+
import {WrappedFieldProps} from "redux-form";
3+
interface IRenderFieldProps<T> extends WrappedFieldProps<T> {
4+
label?: string;
5+
type?: string;
6+
}
27

38
export const required = (value) => (value ? undefined : "Required");
49

510
export const maxLength = (max) => (value) => value && value.length > max ? `Must be ${max} characters or less` : undefined;
611

12+
export const minLength = (min) => (value) => value && value.length < min ? `Must be ${min} characters or more` : undefined;
13+
714
export const numberType = (value) => value && isNaN(Number(value)) ? "Must be a number" : undefined;
815

916
export const minValue = (min) => (value) => value && value < min ? `Must be at least ${min}` : undefined;
@@ -14,12 +21,15 @@ export const tooOld = (value) => value && value > 65 ? "You might be too old for
1421

1522
export const aol = (value) => value && /.+@aol\.com/.test(value) ? "Really? You still use AOL for your email?" : undefined;
1623

17-
export const renderField = ({input, label, type, meta: {touched, error, warning}}) => (
18-
<div>
19-
<label>{label}</label>
24+
export const renderField = (props: IRenderFieldProps<any>) => {
25+
const {input, label, type, meta: {active, touched, error, warning}} = props;
26+
return (
2027
<div>
21-
<input {...input} placeholder={label} type={type} />
22-
{touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}
28+
<label>{props.label}</label>
29+
<div>
30+
<input {...input} placeholder={label} type={type} />
31+
{(active || touched) && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}
32+
</div>
2333
</div>
24-
</div>
25-
);
34+
);
35+
};

0 commit comments

Comments
 (0)