wyboista ścieżka mocy - case study o2.pl
Radosław Rosłaniec
React
alt.js
ES2015 + Babel + Webpack
=
Grid Container
Tabs
Tab
Boxes Container
Box
Title
componentWillMount i (jego) księga tajemnic
//stuff
componentWillMount() {
  window.addEventListener('focus', this.handleWindowFocus)
}
//stuff
          
          
//SSR friendly stuff
componentDidMount() {
  window.addEventListener('focus', this.handleWindowFocus)
}
//SSR friendly stuff
          
        Okej. Zamontowałeś? Odmontuj!
//stuff
componentDidMount() {
  window.addEventListener('focus', this.handleWindowFocus)
  this.intervalId = setInterval(() => {
    console.log('tick')
  }, 1000)
}
componentWillUnmount() {
  window.removeEventListener('focus', this.handleWindowFocus)
  clearInterval(this.intervalId)
}
//stuff
          
        Binding context
class App extends React.Component {
  handleUpdate(event) {
    console.log('update handler')
  }
  render() {
    return (
      <input onChange={this.handleUpdate.bind(this)} />
    )
  }
}
          
          
class App extends React.Component {
  constructor(props) {
    super(props)
    this.handleUpdate = this.handleUpdate.bind(this)
  }
  handleUpdate(event) {
    console.log('update handler')
  }
  render() {
    return (
      <input onChange={this.handleUpdate} />
    )
  }
}
          
        Domyślne wartości
class Title extends React.Component {
  render() {
    return (
      <div>
        {this.props.title || ''}
      </div>
    )
  }
}
Title.displayName = 'Title'
export default Title
          
          
const emptyTitle = ''
class Title extends React.Component {
  render() {
    return (
      <div>
        {this.props.title || emptyTitle}
      </div>
    )
  }
}
Title.displayName = 'Title'
export default Title
          
          
class Title extends React.Component {
  render() {
    return (
      <div>
        {this.props.title}
      </div>
    )
  }
}
Title.displayName = 'Title'
Title.defaultProps = {
  title: ''
}
export default Title
          
        propTypes
class Article extends React.Component {
  render() {
    const video = this.props.video
    return (
      <div>
        {this.props.title}
        <div>
          {video ? <div>
            <span>{video.title}</span>
            <video>
              <source src={video.url} type="video/mp4">
            </video>
          </div> : null}
        </div>
      </div>
    )
  }
}
Article.displayName = 'Article'
Article.defaultProps = {
  title: ''
}
Article.propTypes = {
  title: React.PropTypes.string,
  video: React.PropTypes.shape({
    url: React.PropTypes.string,
    title: React.PropTypes.string
  })
}
export default Article
          
        eslint airbnb
mixins
mixins
komponent wyższego poziomu
  your_project
  |--actions/
  |  |--MyActions.js
  |--sources/
  |  |--MyStoreSource.js
  |--stores/
  |  |--MyStore.js
  |--components/
  |  |--MyComponent.jsx
  |--alt.js
  |--app.js
          
        Show me the code!
//actions/my-store.js
import { alt } from '../alt.js'
class Actions {
  constructor() {
    this.generateActions('fetchItems', 'setItems', 'fetchFailed')
  }
}
export let MyStoreActions = alt.createActions(Actions)
          
          
//stores/my-store.js
import { alt } from '../alt.js'
import { MyStoreActions } from '../actions/my-store.js'
import { MyStoreSource } from '../sources/my-store.js'
class Store {
  constructor() {
    this.bindActions(MyStoreActions)
    this.registerAsync(MyStoreSource)
    this.state = {
      items: []
    }
  }
  onFetchItems() {
    this.getInstance().fetchItems()
  }
  onSetItems(items){
    this.setState({ items })
  }
  onFetchFailed() {
    //handle error
  }
}
export const MyStore = alt.createStore(Store, 'MyStore')
          
          
//sources/my-store.js
import { MyStoreActions } from '../actions/my-store.js'
export const MyStoreSource = {
  fetchItems: {
    remote() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve([1,2,3]);
        }, 1000)
      })
    },
    success:  MyStoreActions.setItems,
    error: MyStoreActions.fetchFailed
  }
}
          
          
//components/my-component.js
import React from 'react'
import AltContainer from 'alt-container'
import { MyStore } from '../stores/my-store.js'
import { MyStoreActions } from '../actions/my-store.js'
import { Items } from './items.js'
class ItemsContainer extends React.Component {
  componentWillMount() {
    MyStoreActions.fetchItems()
  }
  render() {
    return (
      <AltContainer store={MyStore} actions={MyStoreActions}>
        <Items />
      </AltContainer>
    )
  }
}
ItemsContainer.displayName = 'ItemsContainer'
export default ItemsContainer
          
          
//components/items.js
import React from 'react'
class Items extends React.Component {
  render() {
    return (
      <div>
        {this.props.MyStore.items.map(item => <div>{item}</div>)}
      </div>
    )
  }
}
Items.displayName = 'Items'
export default Items
          
        Silne strony alt.js
- prostota
- zarządzanie stanami
- AltContainer