Upgrade to Pro — share decks privately, control downloads, hide ads and more …

frontend_validation.pdf

120734f1a4c9a9ae2d8e5b0deaeee70e?s=47 ktp
September 04, 2019

 frontend_validation.pdf

120734f1a4c9a9ae2d8e5b0deaeee70e?s=128

ktp

September 04, 2019
Tweet

Transcript

  1. Redux middleware Ͱ ϑϩϯτΤϯυόϦσʔγϣϯ Λ࣮૷͢Δ @kato1628

  2. @kato1628 ɾReact, Redux, TypeScript ɾSudachi ɾSwimming

  3. Demo

  4. redux flow

  5. redux flow ʮͲ͏มߋ͞ΕΔ͔ʯˡ ʮͲ͏ৼΔ෣͏͔ʯˡ ʮͲ͏ݟ͑Δ͔ʯˡ

  6. ͲͷϨΠϠʔ΋Ԛͨ͘͠ͳ͍

  7. redux flow (with validation middleware) ಛఆͷBDUJPO͕EJTQBUDI͞Εͨ৔߹ʹͷΈɺ WBMJEBUJPOΛ࣮ߦ͢Δɻ FSSPSTUBUF

  8. Motivation • Fat component/container ͷճආ • ಠཱͨ͠ػߏͰ࣮૷ ≒ ੹຿ͷ෼཭ •

    ֎෦ϥΠϒϥϦ΁ͷґଘճආ • Ұͭͷػߏʹ validation Λू໿
  9. state ͷఆٛ // ͜ΜͳΤϥʔϝοηʔδΛ state ʹ͍࣋ͪͨ errors = { email:

    "Email is required" … }
  10. ΤϥʔϝοηʔδͷܕΛఆٛ # src/reducers/errors.tsx + type ValidateStates = "email"; + type

    ErrorMessage = string; + type Errors = { [key in ValidateStates]?: ErrorMessage }
  11. actionΛఆٛ

  12. 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 + });
  13. reducerΛఆٛ

  14. 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; }
  15. ✓ state (ͲΜͳ஋͔) ✓ action (Կ͕ى͜Δ͔) ✓ reducer (Ͳ͏มߋ͞ΕΔ͔) ☐

    validation middleware (Ͳ͏൑ఆ͢Δ͔)
  16. validation middleware ͷ੹຿ ☑ ൑ఆϩδοΫ => ඞਢνΣοΫɺܻ਺νΣοΫɺ൒֯਺ࣈνΣοΫ…etc ☑ ൑ఆ݁Ռͷ൓ө =>

    action ͷ dispatch
  17. ൑ఆϩδοΫ

  18. validator • จࣈྻόϦσʔγϣϯ • ๛෋ͳόϦσʔγϣϯϝιου https://github.com/validatorjs/validator.js $ yarn add validator

    @types/validator # Example var validator = require('validator'); validator.isEmail('foo@bar.com'); //=> true
  19. middlewareͷ࣮૷

  20. What is middleware? • redux ͷ dispatch Λ֦ு͢Δػߏ • ϐϡΞͳ

    dispatch ͸ϓϨʔϯͳΦϒδΣΫτ͔͠ड͚ औΕͳ͍ • Ex redux-thunk
  21. dispatch ʮSFEVDFSʹBDUJPOΛ౉ͯ͠TUBUFΛߋ৽͢Δʯˡ

  22. Ex. redux-thunk ແ͠ // action ͸ϓϨʔϯͳΦϒδΣΫτΛฦ͢ const increment = ()

    => { return { type: INCREMENT_COUNTER, }; } // dispatch ͸ϓϨʔϯͳΦϒδΣΫτͷΈड͚औΕΔ dispatch(increment())
  23. 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())
  24. middlewareͷܕ

  25. 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 } => ؔ਺Λฦؔ͢਺Λฦؔ͢਺ => ܹ͍͠ΧϦʔԽ
  26. ͪΐͬͱ ԿݴͬͯΔ͔Θ͔Βͳ͍

  27. middlewareͷجຊܗ const validator = ({ dispatch, getState }) => next

    => action => { // ͜͜ʹ൑ఆϩδοΫͱɺaction dispatch Λ࣮૷ // ࣍ͷ middleware ·ͨ͸ store ͷ dispatch ͕ݺͼग़͞ΕΔ return next(action); };
  28. middlewareͷجຊܗ (ܕ༗Γ) + const validator = ({ dispatch, getState }:

    MiddlewareAPI<AppThunkDispatch>) => ( + next: Dispatch + ) => (action: AppAction) => { + return next(action); + }; + + export default validator;
  29. 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;
  30. όϦσʔγϣϯؔ਺ (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 })); // ࣦഊ࣌ + } + };
  31. validation middleware • ൑ఆϩδοΫΛ࣮ߦ • ੒ޭɾࣦഊͦΕͧΕͷ action Λ dispatch •

    validationSuccess • validationFailure
  32. # 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
  33. # 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
  34. Complete!

  35. Pros • Fat component/container ͷճආ • ಠཱͨ͠ػߏͰ࣮૷ ≒ ੹຿ͷ෼཭ •

    ֎෦ϥΠϒϥϦ΁ͷґଘճආ • Ұͭͷػߏʹ validation Λू໿
  36. Cons • Component ͔Βԕ͍ॴʹ validation ͕࣮ ૷͞ΕΔ • middleware Λ஌Βͳ͍ͱཧղ͕೉͍͠

  37. Source https://github.com/kato1628/frontend-validation

  38. Thank you!