Improved form field hooks and remove yup

This commit is contained in:
2020-03-04 15:17:43 +01:00
parent bb00fd442f
commit a1627d3301
8 changed files with 82 additions and 95 deletions
+1
View File
@@ -0,0 +1 @@
$main-color: #8fc;
+19 -3
View File
@@ -1,3 +1,5 @@
@import 'defaults';
:host {
display: block;
}
@@ -5,20 +7,34 @@
input, button {
font-size: 24px;
padding: 5px 10px;
border: solid 1px #ddd;
&:focus {
outline: none;
}
}
input {
border: solid 1px #ddd;
&:focus {
border: solid 1px #aaa;
}
&:valid {
background-color: scale-color($main-color, $lightness: 80%);
}
&.dirty:invalid {
background-color: scale-color(red, $lightness: 80%);
}
}
button {
background-color: #dfc;
border: 0;
background-color: $main-color;
color: #555;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);
&:active {
background-color: #ceb;
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2);
}
&:disabled {
+25 -20
View File
@@ -1,50 +1,55 @@
import { component, html, useState } from 'haunted';
import { spread } from '@open-wc/lit-helpers';
import { useMutation } from '@apollo/react-hooks';
import * as yup from 'yup';
import { useFormField } from './myhooks';
import { AddBook, GetBooks } from './queries'
import Css from './bookform.scss';
const schema = yup.object().shape({
title: yup.string().required(),
author: yup.string().required(),
});
const BookForm = () => {
const [titleProps, setTitle] = useFormField("title");
const [authorProps, setAuthor] = useFormField("author");
const [titleProps, titleMeta] = useFormField("title");
const [authorProps, authorMeta] = useFormField("author");
const [addBook, { loading }] = useMutation(AddBook);
return html`
<style>${Css.toString()}</style>
<input placeholder="book title" ...=${spread(titleProps)}>
<input placeholder="author name" ...=${spread(authorProps)}>
<button @click=${async () => {
<form @submit=${async (e: Event) => {
e.preventDefault();
try {
const newBook = await schema.validate({
const newBook = {
author: authorProps[".value"],
title: titleProps[".value"]
});
};
await addBook({
variables: newBook,
update: (cache, { data }) => {
const { books }: any = cache.readQuery({ query: GetBooks });
cache.writeQuery({ query: GetBooks, data: { books: [...books, data.addBook] }});
cache.writeQuery({
query: GetBooks,
data: { books: [...books, data.addBook] }
});
}
});
setTitle("");
setAuthor("");
titleMeta.reset();
authorMeta.reset();
} catch(e) {
console.log(e);
if (e instanceof yup.ValidationError) {
console.log("validation error");
}
}
}} ?disabled=${loading}>Add book</button>
}}>
<input
required
class=${titleMeta.isDirty ? "dirty" : ""}
placeholder="book title"
...=${spread(titleProps)}>
<input
required
class=${authorMeta.isDirty ? "dirty" : ""}
placeholder="author name"
...=${spread(authorProps)}>
<button ?disabled=${loading}>+ Add book</button>
</form>
`;
}
+4 -2
View File
@@ -1,3 +1,5 @@
@import 'defaults';
:host {
display: block;
font-size: 24px;
@@ -5,7 +7,7 @@
}
p {
border-bottom: solid 1px #cdf;
border-bottom: solid 1px $main-color;
.author {
font-size: 20px;
@@ -14,7 +16,7 @@ p {
}
a {
color: #cdf;
color: $main-color;
font-size: 14px;
text-decoration: none;
}
+3 -1
View File
@@ -1,3 +1,5 @@
@import 'defaults';
:host {
font-family: Ubuntu, sans-serif;
display: block;
@@ -13,5 +15,5 @@
h1 {
margin-top: 0;
background-color: #dfc;
background-color: $main-color;
}
+28 -10
View File
@@ -1,29 +1,47 @@
import { useState, useCallback } from 'haunted';
type FormFieldProps = {
name: string;
type: "text";
'.value': string;
'@input': (e: any) => void;
};
type FormFieldMeta = {
setValue: ReturnType<typeof useState>[1];
isDirty: boolean;
reset: () => void;
};
type FormField = [
{
name: string;
type: "text";
'.value': string;
'@change': (e: any) => void;
},
ReturnType<typeof useState>[1]
FormFieldProps,
FormFieldMeta
];
export const useFormField = (name: string, defaultValue = ""): FormField => {
const [value, setValue] = useState(defaultValue);
const [dirty, setDirty] = useState(false);
const changeHandler = useCallback((e: any) => {
setValue(e.target.value);
}, [setValue]);
setDirty(true);
}, [setValue, setDirty]);
const reset = useCallback(() => {
setValue(defaultValue);
setDirty(false);
}, [setValue, setDirty, defaultValue]);
return [
{
name,
type: "text",
'.value': value,
'@change': changeHandler
'@input': changeHandler
},
setValue
{
setValue,
isDirty: dirty,
reset,
}
];
};