Skip to content

Instantly share code, notes, and snippets.

@egorguscha
Created May 28, 2020 19:13
Show Gist options
  • Save egorguscha/f3d71480b255d95390df04cf39efed81 to your computer and use it in GitHub Desktop.
Save egorguscha/f3d71480b255d95390df04cf39efed81 to your computer and use it in GitHub Desktop.
import {ChangeEvent, FocusEvent} from 'react'
import {
createEvent,
createEffect,
createStore,
forward,
combine,
guard,
sample,
Store,
split,
Event,
} from 'effector'
export const emailChanged = createEvent<string>('email changed')
export const usernameChanged = createEvent<string>('user name changed')
export const passwordChanged = createEvent<string>('password changed')
export const formSubmitted = createEvent<string>('submitted form')
export const blurredInput = createEvent<string>('blurred input')
export const focusedInput = createEvent<string>('focused input')
export const prependEmailChanged = emailChanged.prepend<
ChangeEvent<HTMLInputElement>
>((event) => event.target.value)
export const prependUsernameChanged = usernameChanged.prepend<
ChangeEvent<HTMLInputElement>
>((event) => event.target.value)
export const prependPasswordChanged = passwordChanged.prepend<
ChangeEvent<HTMLInputElement>
>((event) => event.target.value)
export const prependFocus = focusedInput.prepend<FocusEvent<HTMLInputElement>>(
(event) => event.target.name,
)
export const prependBlur = blurredInput.prepend<FocusEvent<HTMLInputElement>>(
(event) => event.target.name,
)
const focusedInputIs = split(focusedInput, {
email: (name) => name === 'email',
username: (name) => name === 'username',
password: (name) => name === 'password',
})
const blurredInputIs = split(blurredInput, {
email: (name) => name === 'email',
username: (name) => name === 'username',
password: (name) => name === 'password',
})
export const $email = createStore('')
export const $username = createStore('')
export const $password = createStore('')
export const $emailError = createStore('')
export const $usernameError = createStore('')
export const $passwordError = createStore('')
type Errors = {
[key: string]: string
}
export const $errors = createStore<Errors>({
username: 'User name should have more than 3 characters',
email: 'Email should have more than 5 characters and contain @',
password: 'Password should have more than 6 characters',
})
export const $isEmailValid = $email.map(
(value) => value.includes('@') && value.length > 5,
)
export const $isUsernameValid = $username.map((value) => value.length > 3)
export const $isPasswordValid = $password.map((value) => value.length > 6)
forward({from: emailChanged, to: $email})
forward({from: usernameChanged, to: $username})
forward({from: passwordChanged, to: $password})
export const $form = combine(
{
email: $isEmailValid,
password: $isPasswordValid,
username: $isUsernameValid,
},
({email, password, username}) => email && password && username,
)
$emailError.reset(focusedInputIs.email)
$usernameError.reset(focusedInputIs.username)
$passwordError.reset(focusedInputIs.password)
const validationWithBlur = (isValid: Store<boolean>, clock: Event<string>) => {
return sample({
source: {errors: $errors, isValid},
clock,
fn: ({errors, isValid}, name) => {
if (!isValid) {
return errors[name]
}
return ''
},
})
}
forward({
from: validationWithBlur($isEmailValid, blurredInputIs.email),
to: $emailError,
})
forward({
from: validationWithBlur($isUsernameValid, blurredInputIs.username),
to: $usernameError,
})
forward({
from: validationWithBlur($isPasswordValid, blurredInputIs.password),
to: $passwordError,
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment