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

Enterprise React

Enterprise React

My Talk from GeeCon Prague 2017 ( biggest Java conference in Czech Republic )

https://2017.geecon.cz/speakers

React in enterprise? You may say: Oh c’mon dude, It’s just a renderer library, how could it be possibly suitable for enterprise where we need so many puzzles for large and maintainable SPA like Dependency Injection, I18n support, Service layer, State Management, Http client, Routing solution, robust Unit testing and E2E solution and many others. In this session I will show you how to get all the pieces together and how we write SPA’s with React at EmbedIT. And yes Typescript is included. P.S.: Pssst, you might be able to ditch Angular after this talk :P

Martin Hochel

October 20, 2017
Tweet

More Decks by Martin Hochel

Other Decks in Technology

Transcript

  1. Martin Hochel SE, Prague / Czech Republic @martin_hotell github.com/Hotell ▪

    @ngPartyCz meetup founder ▪ Author of ngMetadata ▪ Member of @skate_js ▪ ▪ Hello Prague !
  2. “ Any application that can be written in JavaScript, will

    eventually be written in JavaScript. Jeff Atwood
  3. Why function add(a: number, b: number) { return a +

    b; } function add(a, b) { return a + b; } add(1, 3); add(1, '3'); // 4 // ‘13’
  4. import React, { Component } from 'react' import { render

    } from 'react-dom' type Props = { name: string } class HelloMessage extends Component<Props> { render() { return <div>Hello {this.props.name}</div> } } const mountNode = document.getElementById('app') render(<HelloMessage name="Jane" />, mountNode) Component
  5. render() { return <div>Hello {this.props.name}</div> } WTF JSX ? render()

    { return React.createElement( 'div', null, 'Hello ', this.props.name )} { type: 'div', props: { children: ['Hello', 'Jane'], }, }
  6. React - Easy to learn - Functional approach - A

    templating system built right into the language - It’s just JavaScript/Typescript
  7. The Missing puzzle Bundler/Compiler Task runner Package manager HTTP Client

    Service architecture State management Router Forms I18n / l10n Date/time handling Design patterns Dependency Injection Unit/Integration testing E2E testing App scaffold Style guides
  8. Moar Tooling Prettier "fix things for me, please". TSLint "let

    me know about problem, so I can fix them". Husky + Lint-staged Commitizen / Conventional Changelog Standard-versioning
  9. import httpClient from '../http-client' type State = { results: Array<Repo>

    } type Props = {} const SEARCH = '//api.github.com/search/repositories' export class GithubRepoList extends Component<Props, State> { state = { results: [], } componentDidMount() { httpClient.get(`${SEARCH}?q=react`).then(({ data }) => { this.setState({ results: data || [], }) }) } } How to unit test this code ?
  10. DI

  11. <Provider provide={injectables}> <App /> </Provider> const injectables: Injectables = {

    i18n: new I18n(), httpClient: new HttpClient(), endpoints: { search: '...', }, } type Props = Pick<Injectables,'httpClient'|'endpoints'> class GithubRepoList extends Component<Props, State> { componentDidMount() { const { httpClient, endpoints } = this.props httpClient .get<Array<GithubRepo>>(`${endpoints.search}?q=react`) .then(({data}) => { this.setState({results: data || [],}) }) } } const EnhancedGithubRepoList = inject( ({ httpClient, endpoints }: Injectables) => ({ httpClient,endpoints}) )(GithubRepoList)
  12. class GithubRepoList extends Component<Props, State> { componentDidMount() { const {

    httpClient, endpoints } = this.props httpClient .get<Array<GithubRepo>>(`${endpoints.search}?q=react`) .then(({data}) => { this.setState({results: data || [],}) }) } } Tight coupling
  13. export class AuthService { constructor(private httpClient: HttpClient) {} login({ username,

    password, rememberMe }):Promise<Account>{ return this.httpClient .post(LOGIN_URL, { username, password, rememberMe, }) } logout(): Promise<void> { return this.httpClient.get(LOGOUT_URL) } } Services / Business Logic
  14. import { createEpicMiddleware } from 'redux-observable' import { authService }

    from './auth/auth.service' import { userService } from './user/users.service' import rootEpic from './app.epics const epicInjectables = { authService, userService } createEpicMiddleware(rootEpic, { dependencies: epicInjectables, }) Epics DI setup
  15. const fetchUserEpic = ( action$: ActionsObservable<Actions>, store: Store<State>, { userService

    }: Injectables ) => action$ .ofType('FETCH_USER') .mergeMap(({ payload }) => userService.get(payload.id) .then(response => ({ type: 'FETCH_USER_FULFILLED', payload: response, })) ) Epics DI use
  16. State management layer Rest service A Rest service B Service

    Logic Sandbox Presentation layer A Presentation layer B Presentation layer C
  17. export const withUserSandbox = compose( connect(mapStateToProps, mapDispatchToProps), inject(mapInjectables), translate(), reduxForm()

    ) export type UserSandboxProps = {...} Sandboxed HOC composition type Props = {} & UserSandboxProps class UserContainer extends Component<Props>{...} export default withUserSandbox(UserContainer)
  18. App

  19. Summary of Our stack Language - Typescript View Layer -

    React/Preact Bundler/Compiler - Webpack Task runner/Package manager - yarn HTTP Client - facade over Axios State management - Redux + Redux Observable App scaffold/architecture - custom Router - React Router 4 Forms - Redux Forms I18n / l10n - react-i18-next Date/time handling - date-fns Dependency Injection - custom Unit/Integration testing - Jest E2E testing - Testcafe
  20. What did we learn today ? React in Enterprise is

    a thing ! Unidirectional data flow Event driven State management RxJs/Epics reactivity Service Layer / DI Component sandbox Smart/Dumb components