Giter VIP home page Giter VIP logo

react-patterns's Introduction

React

Mostly reasonable patterns for writing React in CoffeeScript.

Table of Contents

  1. Caveat
  2. Organization
  3. Component Organization
  4. Formatting Props
  5. Patterns
  6. Computed Props
  7. Compound State
  8. Sub-render
  9. Transclusion and Layouts
  10. Anti-patterns
  11. Compound Conditions
  12. Cached State in render
  13. Existence Checking
  14. Setting State from Props
  15. Practices
  16. Naming Handle Methods
  17. Naming Events
  18. Using PropTypes
  19. Using Entities
  20. JSX

Caveat

These patterns and practices are birthed from our experience writing React on Rails.

We weight the trade-off of bloating components with get is and sub-render methods. While they clutter a components public interfaces, they are a huge maintainability win.

⬆ back to top


Component Organization

Group methods into logical groups.

  • mixins
  • propTypes
  • getters
  • lifecycle events
  • render
  • event handlers
  • "private" methods
Person = React.createClass
  mixins: [MammalMixin]

  propTypes:
    name: React.PropTypes.string

  getDefaultProps: ->
    name: ''

  getInitialState: ->
    smiling: false

  componentWillMount: ->   # add event listeners (Flux Store, WebSocket, document)

  componentDidMount: ->    # data request (XHR)

  componentWillUnmount: -> # remove event listeners

  render: ->
      React.DOM.div
        className: 'Person'
        onClick:   @handleClick,
          @props.name
          " is smiling" if @state.smiling

   handleClick: ->
     @setState(smiling: !@state.smiling)

  # private

  _doSomethingInOutsideMyself: ->
    # Concerns with outside objects,
    # dirty or duplicated implementations,
    # etc.

⬆ back to top

Formatting Props

Wrap props on newlines for exactly 2 or more.

(Hint: Don't separate props with commas)

# ok
Person({firstName: "Michael"})

# bad
Person({firstName: "Michael", lastName: "Chan", occupation: "Web Developer", favoriteFood: "Drunken Noodles"})

# good
Person
  firstName:    "Michael"
  lastName:     "Chan"
  occupation:   "Web Developer"
  favoriteFood: "Drunken Noodles"
  onChange:     @handleChange

⬆ back to top


Computed Props

Name computed prop methods with the get prefix.

# bad
firstAndLastName: ->
  "#{@props.firstName} #{@props.lastname}"

# good
getFullName: ->
  "#{@props.firstName} #{@props.lastname}"

See: Cached State in render anti-pattern

⬆ back to top


Compound State

Name compound state methods with the is or has prefix:

# bad
happyAndKnowsIt: ->
  @state.happy and @state.knowsIt

# good
isWillingSongParticipant: ->
  @state.happy and @state.knowsIt

hasWorrysomeBehavior: ->
  !@isWillingSongParticipant() and @props.punchesKittens

See: Compound Conditions anti-pattern

⬆ back to top

Sub-render

Use sub-render methods to isolate logical chunks of component UI.

# good
render: ->
  createItem = (itemText) ->
    React.DOM.li(null, itemText)

  React.DOM.ul(null, @props.items.map(createItem))

# better
render: ->
  React.DOM.ul(null, @renderItems())

renderItems: ->
  for itemText in @props.items
    React.DOM.li(null, itemText)

⬆ back to top

Transclusion and Layouts

Use transclusion to wrap components in layout. Don't create one-off components that merge layout and domain components.

# bad
PeopleWrappedInBSRow = React.createClass
  render: ->
    React.DOM.div className: 'row',
      People people: @state.people

# good
BSRow = React.createClass
  render: ->
    React.DOM.div
      className: 'row'
        @props.children

SomeHigherView = React.createClass
  render: ->
    React.DOM.div null,
      BSRow null,
        People(people: @state.people),

This works nicely for complex components—like Tabs or Tables—where you you might need to iterate over children and place them within a complex layout.

⬆ back to top


Cached State in render

Do not keep state in render

# bad
render: ->
  name = 'Mr. ' + @props.name
  React.DOM.div(null, name)

# good
render: ->
  React.DOM.div(null, 'Mr. ' + @props.name)

# good (complex example)
getFormattedBirthDate: ->
  moment(@props.user.bday).format(LL);

render: ->
  React.DOM.div(null, @getFormattedBirthDate())

See: Computed Props pattern

⬆ back to top

Compound Conditions

Do not put compound conditions in render.

#bad
render: ->
  if @state.happy and @state.knowsIt
    React.DOM.div(null, "Knows what it's all about.")

#good
isLikeTotallyHappy: ->
  @state.happy and @state.knowsIt

render: ->
  if @isLikeTotallyHappy()
    React.DOM.div(null, "Knows what it's all about.")

See: Compound State pattern

⬆ back to top

Existence Checking

Do not check existence of prop objects.

#bad
render: ->
  if person?.firstName
    React.DOM.div(null, @props.person.firstName)
  else
    null

#good
getDefaultProps: ->
  person:
    firstName: ''

render: ->
  React.DOM.div(null, @props.person.firstName)

⬆ back to top

Setting State from Props

Do not set state from props without obvious intent.

#bad
getInitialState: ->
  items: @props.items

#good
getInitialState: ->
  items: @props.initialItems

Read: "Props is getInitialState Is an Anti-Pattern"

⬆ back to top


Naming Handler Methods

Name the handler methods after their triggering event.

# bad
render: ->
  React.DOM.div
    onClick: @punchABadger

punchABadger: ->

# good
render: ->
  React.DOM.div
    onClick: @handleClick

handleClick: ->

⬆ back to top

Naming Events

Use custom event names for components Parent-Child event listeners.

Parent = React.createClass
  render: ->
    React.DOM.div
      className: 'Parent'
        Child(onCry: handleCry) # custom event `cry`

  handleCry: ->
    # handle childs' cry

Child = React.createClass
  render: ->
    React.DOM.div
      className: 'Child'
      onChange:  @props.onCry # React DOM event

⬆ back to top

Using PropTypes

Use PropTypes to communicate expectations and log meaningful warnings.

MyValidatedComponent = React.createClass
  propTypes:
    name: React.PropTypes.string

This component will log a warning if it receives name of a type other than string.

Person({name: 1337})
# Warning: Invalid prop `name` of type `number` supplied to `MyValidatedComponent`, expected `string`.

Components may require props

MyValidatedComponent = React.createClass
  propTypes:
    name: React.PropTypes.string.isRequired

This component will now validate the presence of name.

Person()
# Warning: Required prop `name` was not specified in `Person`

Read: Prop Validation

⬆ back to top

Using Entities

Use Reacts String.fromCharCode() for special characters.

# bad
React.DOM.div(null, 'PiCO · Mascot')

# nope
React.DOM.div(null, 'PiCO · Mascot')

# good
React.DOM.div(null, 'PiCO ' + String.fromCharCode(183) + ' Mascot')

Read: JSX Gotchas

⬆ back to top

JSX

Don't use JSX or CJSX in CoffeeScript.

# bad
render: ->
  `(
    <div
     className: "noJSX"
     orClick:   {@handleClick}>
      Save the children.
    </div>
   )`

#good
render: ->
  React.DOM.div
    className: "noJSX"
    onClick:   @handleClick,
      'Save the children.'

Read: CoffeeScript and JSX for more on our decision to avoid JSX.

⬆ back to top

react-patterns's People

Contributors

chantastic avatar

Watchers

James Cloos avatar Robert Mosolgo avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.