Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
react-form-with-constraints
Advanced tools
Simple form validation for React
npm install react-form-with-constraints
Check the changelog for breaking changes and fixes between releases.
⚠️ Client side validation is cosmetic, you should not rely on it to enforce security
<form>
<label for="email">Email:</label>
<input type="email" id="email" required>
<button type="submit">Submit</button>
</form>
The required
HTML5 attribute specifies that the user must fill in a value, type="email"
checks that the entered text looks like an email address.
Resources:
<FieldFeedback when="valueMissing">My custom error message</FieldFeedback>
<FieldFeedback when={value => ...}>
<FieldFeedback ... warning>
, <FieldFeedback ... info>
react-form-with-constraints-bootstrap
react-form-with-constraints-material-ui
react-form-with-constraints-native
<input type="password" name="password"
value={this.state.password} onChange={this.handleChange}
required pattern=".{5,}" />
<FieldFeedbacks for="password">
<FieldFeedback when="valueMissing" />
<FieldFeedback when="patternMismatch">
Should be at least 5 characters long
</FieldFeedback>
<FieldFeedback when={value => !/\d/.test(value)} warning>
Should contain numbers
</FieldFeedback>
<FieldFeedback when={value => !/[a-z]/.test(value)} warning>
Should contain small letters
</FieldFeedback>
<FieldFeedback when={value => !/[A-Z]/.test(value)} warning>
Should contain capital letters
</FieldFeedback>
</FieldFeedbacks>
CodePen basic Password example: https://codepen.io/tkrotoff/pen/BRGdqL (StackBlitz version)
React Native example (React classes):
iOS | Android |
---|---|
Other examples from the examples directory:
The API works the same way as React Router:
<Router>
<Route exact path="/" component={Home} />
<Route path="/news" component={NewsFeed} />
</Router>
It is also inspired by AngularJS ngMessages.
If you had to implement validation yourself, you would end up with a global object that tracks errors for each field.
react-form-with-constraints works similarly.
It uses React context to share the FieldsStore
object across FieldFeedbacks
and FieldFeedback
.
The API reads like this: "for field when constraint violation display feedback", example:
<FieldFeedbacks for="password">
<FieldFeedback when="valueMissing" />
<FieldFeedback when="patternMismatch">Should be at least 5 characters long</FieldFeedback>
</FieldFeedbacks>
for field "password"
when constraint violation "valueMissing" display <the HTML5 error message (*)>
when constraint violation "patternMismatch" display "Should be at least 5 characters long"
Async support works as follow:
<FieldFeedbacks for="username">
<Async
promise={checkUsernameAvailability} /* Function that returns a promise */
then={available => available ?
<FieldFeedback key="1" info style={{color: 'green'}}>Username available</FieldFeedback> :
<FieldFeedback key="2">Username already taken, choose another</FieldFeedback>
// Why key=*? Needed otherwise React gets buggy when the user rapidly changes the field
}
/>
</FieldFeedbacks>
Trigger validation:
function MyForm() {
const form = useRef(null);
async function handleChange({ target }) {
// Validates only the given fields and returns Promise<Field[]>
await form.current.validateFields(target);
}
async function handleSubmit(e) {
e.preventDefault();
// Validates the non-dirty fields and returns Promise<Field[]>
await form.current.validateForm();
if (form.current.isValid()) console.log('The form is valid');
else console.log('The form is invalid');
}
return (
<FormWithConstraints ref={form} onSubmit={handleSubmit} noValidate>
<input
name="username"
onChange={handleChange}
required minLength={3}
/>
<FieldFeedbacks for="username">
<FieldFeedback when="tooShort">Too short</FieldFeedback>
<Async
promise={checkUsernameAvailability}
then={available => available ?
<FieldFeedback key="1" info style={{color: 'green'}}>Username available</FieldFeedback> :
<FieldFeedback key="2">Username already taken, choose another</FieldFeedback>
}
/>
<FieldFeedback when="*" />
</FieldFeedbacks>
</FormWithConstraints>
);
}
Important note:
If a field (i.e an <input>
) does not have a matching FieldFeedbacks
, the library won't known about this field (and thus won't perform validation).
The field name should match FieldFeedbacks.for
:
<input name="MY_FIELD" ...>
<FieldFeedbacks for="MY_FIELD">
...
</FieldFeedbacks>
for: string
=> reference to a name
attribute (e.g <input name="username">
), should be unique to the current formstop?: 'first' | 'first-error' | 'first-warning' | 'first-info' | 'no'
=>
when to stop rendering FieldFeedback
s, by default stops at the first error encountered (FieldFeedback
s order matters)Note: you can place FieldFeedbacks
anywhere, have as many as you want for the same field
, nest them, mix them with FieldFeedback
... Example:
<input name="username" ... />
<FieldFeedbacks for="username" stop="first-warning">
<FieldFeedbacks>
<FieldFeedback ... />
<Async ... />
<FieldFeedbacks stop="first-info">
...
</FieldFeedbacks>
</FieldFeedbacks>
<FieldFeedback ... />
<Async ... />
</FieldFeedbacks>
<FieldFeedbacks for="username" stop="no">
...
</FieldFeedbacks>
when?
:
ValidityState
as a string => HTML5 constraint violation name'*'
=> matches any HTML5 constraint violation'valid'
=> displays the feedback only if the field is valid(value: string) => boolean
=> custom constrainterror?: boolean
=> treats the feedback as an error (default)warning?: boolean
=> treats the feedback as a warninginfo?: boolean
=> treats the feedback as an infochildren
=> what to display when the constraint matches; if missing, displays the HTML5 error message if anyAsync<T>
=> Async version of FieldFeedback
(similar API as react-promise)
promise: (value: string) => Promise<T>
=> a promise you want to wait forpending?: React.ReactNode
=> runs when promise is pendingthen?: (value: T) => React.ReactNode
=> runs when promise is resolvedcatch?: (reason: any) => React.ReactNode
=> runs when promise is rejectedvalidateFields(...inputsOrNames: Array<Input | string>): Promise<Field[]>
=>
Should be called when a field
changes, will re-render the proper FieldFeedback
s (and update the internal FieldsStore
).
Without arguments, all fields ($('[name]')
) are validated.
validateFieldsWithoutFeedback(...inputsOrNames: Array<Input | string>): Promise<Field[]>
=>
Validates only all non-dirty fields (won't re-validate fields that have been already validated with validateFields()
),
If you want to force re-validate all fields, use validateFields()
.
Might be renamed to validateNonDirtyFieldsOnly()
or validateFieldsNotDirtyOnly()
in the future?
validateForm(): Promise<Field[]>
=>
Same as validateFieldsWithoutFeedback()
without arguments, typically called before to submit the form
.
Might be removed in the future?
isValid(): boolean
=> should be called after validateFields()
, validateFieldsWithoutFeedback()
or validateForm()
, indicates if the fields are valid
hasFeedbacks(): boolean
=> indicates if any of the fields have any kind of feedback
resetFields(...inputsOrNames: Array<Input | string>): Field[]
=>
Resets the given fields and re-render the proper FieldFeedback
s.
Without arguments, all fields ($('[name]')
) are reset.
Field
=>
{
name: string;
validations: { // FieldFeedbackValidation[]
key: number;
type: 'error' | 'warning' | 'info' | 'whenValid';
show: boolean | undefined;
}[];
isValid: () => boolean
}
If you want to style <input>
, use <Input>
instead: it will add classes is-pending
, has-errors
, has-warnings
, has-infos
and/or is-valid
on <input>
when the field is validated.
Example: <Input name="username" />
can generate <input name="username" class="has-errors has-warnings">
FYI react-form-with-constraints-bootstrap
and react-form-with-constraints-material-ui
already style the fields to match their respective frameworks.
react-form-with-constraints needs ValidityState
which is supported by all modern browsers and IE 11.
It also needs a polyfill such as core-js to support IE 11, see React JavaScript Environment Requirements.
You can use HTML5 attributes like type="email"
, required
, minlength
...
<label htmlFor="email">Email</label>
<input type="email" name="email" id="email"
value={this.state.email} onChange={this.handleChange}
required />
<FieldFeedbacks for="email">
<FieldFeedback when="*" />
</FieldFeedbacks>
...and/or rely on when
functions:
<label htmlFor="email">Email</label>
<input name="email" id="email"
value={this.state.email} onChange={this.handleChange} />
<FieldFeedbacks for="email">
<FieldFeedback when={value => value.length === 0}>Please fill out this field.</FieldFeedback>
<FieldFeedback when={value => !/\S+@\S+/.test(value)}>Invalid email address.</FieldFeedback>
</FieldFeedbacks>
In the last case you will have to manage translations yourself (see SignUp example).
type="hidden"
, readonly
or disabled
input won't trigger any HTML5 form constraint validation like required
, see https://codepen.io/tkrotoff/pen/gdjVNvv0.19.1 (2022/07/22)
FAQs
Simple form validation for React
The npm package react-form-with-constraints receives a total of 626 weekly downloads. As such, react-form-with-constraints popularity was classified as not popular.
We found that react-form-with-constraints demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.