Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
frontend_validation.pdf
Search
ktp
September 04, 2019
Programming
1.7k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
frontend_validation.pdf
ktp
September 04, 2019
More Decks by ktp
See All by ktp
個人プロダクトのはなし@社内LT会
kato1628
1
210
Other Decks in Programming
See All in Programming
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
220
ユニットテストの先へ:テスト技法で要求・仕様を整理するJava開発実践 / Beyond_Unit_Testing_Practical_Java_Development_Techniques_for_Organizing_Requirements_and_Specifications
shimashima35
0
350
Lessons from Spec-Driven Development
simas
PRO
0
140
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
500
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
250
CSC307 Lecture 17
javiergs
PRO
0
310
OSもどきOS
arkw
0
450
JJUG CCC 2026 Spring: JSpecify で実現する Kotlin フレンドリーな Java API 設計
ternbusty
1
140
LLM Plugin for Node-REDの利用方法と開発について
404background
0
160
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
17
5.9k
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
1
610
CLIであることを活かしたGitHub Copilot CLI活用術 / GitHub Copilot CLI Pro Tips & Tricks
nao_mk2
1
1.2k
Featured
See All Featured
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
エンジニアに許された特別な時間の終わり
watany
107
250k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
200
Technical Leadership for Architectural Decision Making
baasie
3
400
Building AI with AI
inesmontani
PRO
1
1.1k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.5k
Designing Experiences People Love
moore
143
24k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
250
Transcript
Redux middleware Ͱ ϑϩϯτΤϯυόϦσʔγϣϯ Λ࣮͢Δ @kato1628
@kato1628 ɾReact, Redux, TypeScript ɾSudachi ɾSwimming
Demo
redux flow
redux flow ʮͲ͏มߋ͞ΕΔ͔ʯˡ ʮͲ͏ৼΔ͏͔ʯˡ ʮͲ͏ݟ͑Δ͔ʯˡ
ͲͷϨΠϠʔԚͨ͘͠ͳ͍
redux flow (with validation middleware) ಛఆͷBDUJPO͕EJTQBUDI͞Εͨ߹ʹͷΈɺ WBMJEBUJPOΛ࣮ߦ͢Δɻ FSSPSTUBUF
Motivation • Fat component/container ͷճආ • ಠཱͨ͠ػߏͰ࣮ ≒ ͷ •
֎෦ϥΠϒϥϦͷґଘճආ • Ұͭͷػߏʹ validation Λू
state ͷఆٛ // ͜ΜͳΤϥʔϝοηʔδΛ state ʹ͍࣋ͪͨ errors = { email:
"Email is required" … }
ΤϥʔϝοηʔδͷܕΛఆٛ # src/reducers/errors.tsx + type ValidateStates = "email"; + type
ErrorMessage = string; + type Errors = { [key in ValidateStates]?: ErrorMessage }
actionΛఆٛ
actionΛఆٛ # src/actions/actions.tsx + export const validationSuccess = (key: ValidateStates)
=> ({ + type: AppActionTypes.VALIDATION_SUCCESS as const, + key + }); + export const validationFailure = (errors: Errors) => ({ + type: AppActionTypes.VALIDATION_FAILURE as const, + errors + });
reducerΛఆٛ
reducerΛఆٛ # src/reducers/errors.tsx export const errors = (state = initialErrors,
action: AppAction): Errors => { switch (action.type) { + case AppActionTypes.VALIDATION_FAILURE: // ࣦഊ࣌ + return { + ...state, + ...action.errors + }; + case AppActionTypes.VALIDATION_SUCCESS: // ޭ࣌ + const nextState = { ...state }; + delete nextState[action.key]; + return nextState; default: return state; }
✓ state (ͲΜͳ͔) ✓ action (Կ͕ى͜Δ͔) ✓ reducer (Ͳ͏มߋ͞ΕΔ͔) ☐
validation middleware (Ͳ͏ఆ͢Δ͔)
validation middleware ͷ ☑ ఆϩδοΫ => ඞਢνΣοΫɺܻνΣοΫɺ֯ࣈνΣοΫ…etc ☑ ఆ݁Ռͷө =>
action ͷ dispatch
ఆϩδοΫ
validator • จࣈྻόϦσʔγϣϯ • ๛ͳόϦσʔγϣϯϝιου https://github.com/validatorjs/validator.js $ yarn add validator
@types/validator # Example var validator = require('validator'); validator.isEmail('
[email protected]
'); //=> true
middlewareͷ࣮
What is middleware? • redux ͷ dispatch Λ֦ு͢Δػߏ • ϐϡΞͳ
dispatch ϓϨʔϯͳΦϒδΣΫτ͔͠ड͚ औΕͳ͍ • Ex redux-thunk
dispatch ʮSFEVDFSʹBDUJPOΛͯ͠TUBUFΛߋ৽͢Δʯˡ
Ex. redux-thunk ແ͠ // action ϓϨʔϯͳΦϒδΣΫτΛฦ͢ const increment = ()
=> { return { type: INCREMENT_COUNTER, }; } // dispatch ϓϨʔϯͳΦϒδΣΫτͷΈड͚औΕΔ dispatch(increment())
Ex. redux-thunk ༗Γ // function Λฦ͢ action Λఆٛ const incrementAsync
= () => { return (dispatch) => { setTimeout(() => { // Yay! Can invoke sync or async actions with `dispatch` dispatch(increment()); // ͦͷதͰ͞Βʹ action Λ dispatch }, 1000); }; } // dispatch function ड͚औΕΔ dispatch(incrementAsync())
middlewareͷܕ
middlewareͷܕ # src/node_modules/redux/index.d.ts export interface Middleware< DispatchExt = {}, S
= any, D extends Dispatch = Dispatch > { (api: MiddlewareAPI<D, S>): ( next: Dispatch<AnyAction> ) => (action: any) => any } => ؔΛฦؔ͢Λฦؔ͢ => ܹ͍͠ΧϦʔԽ
ͪΐͬͱ ԿݴͬͯΔ͔Θ͔Βͳ͍
middlewareͷجຊܗ const validator = ({ dispatch, getState }) => next
=> action => { // ͜͜ʹఆϩδοΫͱɺaction dispatch Λ࣮ // ࣍ͷ middleware ·ͨ store ͷ dispatch ͕ݺͼग़͞ΕΔ return next(action); };
middlewareͷجຊܗ (ܕ༗Γ) + const validator = ({ dispatch, getState }:
MiddlewareAPI<AppThunkDispatch>) => ( + next: Dispatch + ) => (action: AppAction) => { + return next(action); + }; + + export default validator;
middlewareͷ࣮ const validator = ({ dispatch, getState }: MiddlewareAPI<AppThunkDispatch>) =>
( next: Dispatch ) => (action: AppAction) => { + switch (action.type) { + case AppActionTypes.UPDATE_EMAIL: // dispatchʹόϦσʔγϣϯؔΛ͢ʢredux-thunk Λ༻ʣ + dispatch(validateEmail(action.email)); + break; + default: + break; } return next(action); }; export default validator;
όϦσʔγϣϯؔ (thunk actin) + const validateEmail = (email: string): AppThunkAction<void>
=> dispatch => { + let errorMessage: string = ""; // validator ΛͬͯඞਢνΣοΫ + if (isEmpty(email)) { + errorMessage = "Email is required."; + } + if (errorMessage === "") { + dispatch(validationSuccess(“email")); // ޭ࣌ + } else { + dispatch(validationFailure({ email: errorMessage })); // ࣦഊ࣌ + } + };
validation middleware • ఆϩδοΫΛ࣮ߦ • ޭɾࣦഊͦΕͧΕͷ action Λ dispatch •
validationSuccess • validationFailure
# src/index.tsx + import thunk from “redux-thunk"; + import validator
from "./middleware/validator"; - const store = createStore(reducer) + const store = createStore(reducer, applyMiddleware(thunk, validator)); applyMiddleware
# src/containers/AppContainer.tsx + const mapStateToProps = (state: AppState) => ({
+ errors: state.errors + }); # src/components/App.tsx + const App: React.FC<AppProps> = ({ errors, onChangeEmail }) => { ~~ + <p>{errors.email}</p> display errors
Complete!
Pros • Fat component/container ͷճආ • ಠཱͨ͠ػߏͰ࣮ ≒ ͷ •
֎෦ϥΠϒϥϦͷґଘճආ • Ұͭͷػߏʹ validation Λू
Cons • Component ͔Βԕ͍ॴʹ validation ͕࣮ ͞ΕΔ • middleware ΛΒͳ͍ͱཧղ͕͍͠
Source https://github.com/kato1628/frontend-validation
Thank you!