React on Rails (part-2)

React on Rails.jpg

So we already learned about React and how to set it up in our Rails application. If you missed the first part go through here https://viblo.asia/mksaikat/posts/OREkwZZRelN . Now we will talk about the most important feature of react "Component".

Component

Component is the part of the HTML rendered and managed by React. It is made by state and properties and always composed of smaller React components. A component is a stand-alone and self-contained part of the UI code. We can reuse it anywhere we want and use it to compose bigger components.

The three basic parts of component are,

State

Changing state of a component is one way to re-render your component, resulting in a visible change. React components maintain their dynamic part of data separated from the static data for performance reasons. Manipulating components is done by changing the state — doing so forces React to re-render a component.

By default, when instantiating a component, the state is empty — it is a null value. We can change it using the setState method which every component has. State is accessible in most component methods under this.state instance variable.

This is a small example of how we can initialize state in a component,

Greeter = React.createClass
  getInitialState: ->
    name: 'World'

  render: ->
    React.DOM.span
      className: 'greeter-message'
      "Hello, #{@state.name}!"

greeter = React.createFactory(Greeter)
component = ReactDOM.render(greeter(), document.getElementById("greeter-placeholder"))
component.setState(name: 'my first React component!')

Properties

Properties are a very helpful part of all React components we create. Properties are immutable. That means that after construction of the component they stay the unchanged. Forever.

The basic idea is that properties hold data which wont change during the whole lifecycle of the component — whether to instantiate a default state or to reference this data. It can be considered as‘constants’ in the component — we may reference them during rendering or setting component’s behaviour, but we shouldn’t change them.

React components get the properties values the moment they instantiated. Normally we use them to create the initial state and set values that need to be accessible and are constant through the whole lifecycle of a component.

Greeter = React.createClass
  getInitialState: ->
    name: @props.initialName || "World"

  render: ->
    React.DOM.span
      className: 'greeter-message'
      "Hello, #{@state.name}!"

rootNode  = document.getElementById("greeter-box")
greeter = React.createFactory(Greeter)

component = ReactDOM.render(greeter(initialName: "Andy"), rootNode)
component.setState(name: 'Marcin')
React.unmountComponentAtNode(rootNode)
component = ReactDOM.render(greeter(), rootNode)

Render method

All React components must have the render method. The render method always return a React component. It has access to properties and state and in here we decide what will be the outcome of the render method. The render method should only generate HTML and assign key/refs/event handlers to it.

This method is called automatically by React in these two situations:

• If the state changes. It also calls componentDidUpdate method.

• If we mount component using ReactDOM.render. It also calls the componentDidMount method.

An important assumption that React makes about your render method is that it is idempotent - that means, calling it multiple times with the same properties and state will always result in the same outcome.

So what can we do in our render method,

• Computing the auxiliary data you may need in your user interface from state and properties.

• Creating components based on properties and state.

• Define the HTML structure of a user interface part.

example:

  PersonGreeter = React.createClass
    getInitialState: ->
      person: new Person('Bruce', 'Wayne')

    personFullName: (person) ->
      [person.firstName, person.lastName].join(" ")

    render: ->
      fullName = @personFullName(@state.person) # Computing full name of person

      @greeterBox(
        @greeterSpan("Hello, #{fullName}!")
      )

    greeterBox: (children) ->
      React.DOM.div
        className: 'greeter-box'
        children

    greeterSpan: (children) ->
      React.DOM.span
        className: 'greeter-text'
        children

Resource:

https://facebook.github.io/react/index.html

https://github.com/reactjs/react-rails

http://blog.arkency.com/rails-react/