3.0.0 • Published 7 years ago

@schibstedspain/ddd-react-redux v3.0.0

Weekly downloads
1
License
ISC
Repository
-
Last release
7 years ago

DDD React Redux

Install

$ npm install @schibstedspain/ddd-react-redux

Usage

// entry.js

import React from 'react'
import {render} from 'react-dom'
import {Provider} from 'ddd-react-redux'

import Domain from '@schibstedspain/domain'
import Rosetta from '@schibstedspain/rosetta'
import Polyglot from '@schibstedspain/rosetta/lib/adapters/polyglot'

const DEFAULT_CULTURE = 'es-ES'
const DEFAULT_CURRENCY = 'EUR'

const domain = new Domain()
const i18n = new Rosetta({ adapter: new Polyglot() })

i18n.languages = {'es-ES': {}}
i18n.culture = DEFAULT_CULTURE
i18n.currency = DEFAULT_CURRENCY

render(
  <Provider i18n={i18n} domain={domain}>
    <App />
  </Provider>,
  document.getElementById('root')
)

O pasando directamente el store, si necesitas usarlo fuera del arbol de componentes de react:

// entry.js

import React from 'react'
import {render} from 'react-dom'
import {Provider, createStore} from 'ddd-react-redux'

import Domain from '@schibstedspain/domain'
import Rosetta from '@schibstedspain/rosetta'
import Polyglot from '@schibstedspain/rosetta/lib/adapters/polyglot'

const DEFAULT_CULTURE = 'es-ES'
const DEFAULT_CURRENCY = 'EUR'

const domain = new Domain()
const i18n = new Rosetta({ adapter: new Polyglot() })

i18n.languages = {'es-ES': {}}
i18n.culture = DEFAULT_CULTURE
i18n.currency = DEFAULT_CURRENCY

const store = createStore(domain)

render(
  <Provider i18n={i18n} store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

Passing Config to your components

// components/Search.js

import React, {Component} from 'react'
import PropTypes from 'prop-types'

import {compose, mapConfigToProps} from 'ddd-react-redux'

class Search extends Component {
  const {gradesConfig} = this.props
  render () {
    return (
      <div className='Search'>
        <input value={this.state.term} onChange={e => this.setState({term: e.target.value})} />
        <select>
          { gradesConfig.map(grade => <option key={grade} value={grade}>{grade}</option>) }
        </select>
        <button onClick={this.handleSearch}>Search</button>
      </div>
    )
  }

  handleSearch = e => {
    const {listStudentsUseCase} = this.props
    const {term} = this.state
    listStudentsUseCase({term})
  }
}

export default compose(
  mapConfigToProps('grades')
)(Search)

Or Using locals HoC to avoid use the global state when you dont need it

import {withLocalService, mapServiceToProps, mapResponseToProps, compose} from '@schibstedspain/ddd-react-redux'

const Home = ({
  history,
  listStudients,
  listStudientsError,
  listStudientsParams,
  listStudientsUseCase
}, {i18n}) => {

  // we control the error, so we render something if we have one
  if (listStudientsError !== undefined) {
    return <h1>Ey! I got this error:<br />{listStudientsError.toString()}</h1>
  }

  // no info yet, call the use case now!
  listStudients === undefined &&
    listStudientsError === undefined && // we have to be sure we don't get a weird loop here!
    listStudientsUseCase()

  return (
    <div className='Home'>
      <Grid images={listStudients} />
      <LoadingOverlay display={listStudients === undefined} />
    </div>
  )
}

Home.displayName = 'Home'
Home.contextTypes = {
  i18n: PropTypes.object
}
Home.propTypes = {
  listStudients: PropTypes.array,
  listStudientsError: PropTypes.any,
  listStudientsParams: PropTypes.object,
  listStudientsUseCase: PropTypes.func,
  history: PropTypes.shape({
    push: PropTypes.func
  })
}

export default withLocalService('list_studients_use_case')(Home)

Using UI HoC to manage not relative Domain updates

import {mapUIServiceToProps, mapUIResponseToProps, compose} from '@schibstedspain/ddd-react-redux'

const Home = ({
  history,
  setOfflineUI,
  offlineUI
}, {i18n}) => {

  setTimeout(() => {
    setOfflineUI(true)
  }, 3000)


  // no info yet, call the use case now!
  return (
    <div className='Home'>
      {offlineUI ? 'We are Offline' : 'We are Online'}
    </div>
  )
}

Home.displayName = 'Home'
Home.contextTypes = {
  i18n: PropTypes.object
}
Home.propTypes = {
  offlineUI: PropTypes.bool,
  setOfflineUI: PropTypes.func,
  history: PropTypes.shape({
    push: PropTypes.func
  })
}

export default compose(
  mapUIResponseToProps('offline')
  mapUIServiceToProps('offline')
)('list_studients_use_case')(Home)

Comunicación entre componentes:

import { withLocalService, withStreamService, compose } from '@schibstedspain/ddd-react-redux'

class Home extends PureComponent {
  static displayName = 'Home'
  static contextTypes = {
    i18n: PropTypes.object
  }
  static propTypes = {
    listStudients$: PropTypes.array,
    listStudients$Error: PropTypes.object,
    listStudients: PropTypes.array,
    listStudientsLoading: PropTypes.bool,
    listStudientsCalled: PropTypes.bool,
    listStudientsUseCase: PropTypes.func,
    history: PropTypes.shape({
      push: PropTypes.func
    })
  }

  componentDidMount () {
    const {
      listStudientsCalled,
      listStudientsUseCase
    } = this.props

    !listStudientsCalled &&
    listStudientsUseCase()
  }

  render () {
    const {
      history,
      listStudients$,
      listStudients$Error
    } = this.props
    const {i18n} = this.context

    if (listStudients$Error !== undefined) {
      return <h1>Ey! I got this error:<br />{listStudients$Error.toString()}</h1>
    }

    return (
      <div className='Home'>
        <AppCanvas scrollingTechniques>
          <AppBar title={i18n.t('TITLE')} showMenuIconButton={false} />
          <Content>
            <div className='Home-SearchWrapper'><Search /></div>
            <div className='Home-GridWrapper'><Grid images={listStudients$} /></div>
            <div className='Home-FAVWrapper'><FAVMenu onClickItem={({item}) => {
              const path = item === FAVMenu.ITEMS.SINGLE ? '/create/single' : '/create/multiples'
              history.push(path)
            }} /></div>
          </Content>
        </AppCanvas>
        <LoadingOverlay display={listStudients$ === undefined} />
      </div>
    )
  }
}

export default compose(
  withLocalService('list_studients_use_case'),
  withStreamService('list_studients_use_case')
)(Home)

TODO

  • Gestionar adecuadamente los errores en los casos de uso
  • Obtener la configuración usando otro HoC. del tipo export default config('provinces', 'courses')(Search)
3.0.0

7 years ago

3.0.0-beta.2

7 years ago

3.0.0-beta.1

7 years ago

3.0.0-beta.0

7 years ago

2.3.0

7 years ago

2.2.0

7 years ago

2.1.0

7 years ago

2.0.0

7 years ago

1.3.0

7 years ago

1.2.0

7 years ago

1.1.0

7 years ago

1.0.0

7 years ago