React Hook Formとyupでフォームにバリデーションかけてます。
で、問題は、inputのtypeがnumberで、yupではnumber or nullでバリデーションかけたいとき。
yup.number()
yup.number().nullable()
だと、数字はいけますが、nullが入りません。
must be a `number` type, but the final value was: `NaN` (cast from the value `""`).
どうすればええにゃーってなっていたところ、
上記のissueで、下記のコメントが参考になりそうと教えてもらった。
https://github.com/jquense/yup/issues/298#issuecomment-678278303
これでいってみる
yup.string().matches(/^\d*$/, 'Wrong number')
バリデーションとしてのエラーは出なかった。が、consoleにエラーが。
Uncaught (in promise) {data: null, errors: Array(1)}
"Variable 'var' has an invalid value. Expected type 'Int' but was 'String'."
なるほどたしかに。GraphQL的にはIntなのですが、stringを入れようとしているのでエラー出た。だめそう。
うーどうしよう、と思ってたら1つ下に気になるコメントが
https://github.com/jquense/yup/issues/298#issuecomment-701305514
これを真似してみる
yup .number() .nullable() .transform((value, originalValue) => String(originalValue).trim() === '' ? null : value )
これでいけたあああ!!!!nullも入るし数字も入る!!!!
このtransformとやらでなんか良い感じにしてくれているっぽい。これがないとエラー出てだめだったからな…でもちょっとこのtransformがなにしてるかちゃんとわかりきっていない。inputの値とってきてstring化してtrimとやらでとってきたものが空ならnull、あったら数字を値そのまま数字で返してる感じがする。
ちなみに結局整数で0以上で…みたいな条件も追加したので
yup .number() .typeError('数字を入力してください') .integer('整数を入力してください') .min(0, '0以上の数字を入れてください') .nullable() .transform((value, originalValue) => String(originalValue).trim() === '' ? null : value )
としました。