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
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
190
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
2
270
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
3
780
JAWS-UG横浜 #102 AWSサ終供養LT会 成仏できない AWS サービスたち 〜本日、三体供養します〜
maroon1st
0
360
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
4
410
ここ半年くらいでAIに作らせたR用ツール
eitsupi
0
380
楽しそうなつよつよエンジニアと目が死んでる僕/A brilliant engineer having a blast, and dead-eyed me.
3l4l5
2
180
為什麼你並不需要ViewModel / No, you don't need a ViewModel
lovee
1
490
Google Apps Script で Ruby を動かす
kawahara
0
220
ソフトウェアエンジニアにとっての生成AI - 特性を知って使い倒す / generative ai for software enginner
kishida
2
310
yield再入門 #phpcon
o0h
PRO
0
1k
Jindong: Introducing Declarative Haptics in Compose Multiplatform
l2hyunwoo
0
110
Featured
See All Featured
Building Adaptive Systems
keathley
44
3.2k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
210
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
480
The Invisible Side of Design
smashingmag
301
52k
The Curse of the Amulet
leimatthew05
2
14k
Done Done
chrislema
186
16k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
480
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
470
The Curious Case for Waylosing
cassininazir
1
450
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
200
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.4k
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!