Hướng dẫn setup môi trường chạy rails + react để chạy jsx và ES6

Lời dẫn

Ở bài viết này mình xin chia sẻ việc setup môi trường để chạy rails với react khi các bạn viết jsx và es6.

Khi mới làm quen với react, mình rất khó khăn và mất thời gian cho việc setup này. Hy vọng bài viết sẽ giúp các bạn mới tìm hiểu react có thể dễ dàng setup.

Các bạn có thể tham khảo src tại đây: Github

Setup

Trước hết các bạn cần 1 project rails

rails new sample_rails_react

trong Gemfile

gem 'browserify-rails'
gem 'react-rails'

Việc setup cho từng gem, các bạn đọc trên github của mỗi trang dùm mình, vì việc đó không có gì phức tạp.

trong application.rb thêm dòng

config.browserify_rails.commandline_options = "-t babelify --extension=\"es6.js\""

tại root của prj, các bạn tạo file package.json với nội dung

{
  "dependencies": {
    "babelify": "^7.2.0",
    "browserify": "~10.2.4",
    "browserify-incremental": "^3.0.1",
    "jquery": "^2.2.3",
    "jquery-ujs": "^1.2.1",
    "react": "^15.0.1",
    "react-dom": "^15.0.1",
    "react-swal": "^1.0.0"
  },
  "devDependencies": {
    "babel-preset-es2015": "^6.6.0",
    "babel-preset-react": "^6.5.0"
  }
}

sau đó chạy

sudo npm install

Nói thêm 1 chút về npm. Theo trang chủ thì

npm is the package manager for JavaScript. Find, share, and reuse packages of code from hundreds of thousands of developers — and assemble them in powerful new ways.

và file package.json là nơi để chứa các javascrip packages, theo mình thì các bạn có thể hiểu nó giống như Gemfile trong rails vậy, và lệnh npm install cũng như bundle install.

Các bạn cũng có thể cài đặt npm step by step bắt đầu bằng

npm init

sau đó các bạn sẽ được hỏi để lựa chọn các configuration như name, version, author... Nhưng mình lười, nên thường tạo file package.json và thêm các packages cần thiết.

Và cuối cùng, các bạn tạo 1 file .babelrc ở thư mục root của prj

{
  "presets": [ "es2015", "react" ]
}

Theo mình hiểu, file này là để compile code từ es6 và react sang es5. Ah, mình nói thêm, es6 chính là es2015 và es5 là kiểu javascript mà lâu nay các bạn vẫn đang viết(mình cũng k biết giải thích thế nào 😄). Cái này mình k rõ lắm, các bạn cùng trao đổi để hiểu rõ hơn nhé.

OK, bây giờ mọi việc có lẽ đã hoàn tất. Tiếp theo, các bạn chỉ việc code thôi.

Sample code

Tạo 1 scaffold books(title: string, author: string)

rails g scaffold book title:string author:string

trong app/javascripts/components.js

const app = window.app = global.app = {};

import IndexBook from './components/books/IndexBook.es6'
import BookRow from './components/books/BookRow.es6'

app.IndexBook = IndexBook;
app.BookRow = BookRow;

import IndexBook from './components/books/IndexBook.es6' mục đích là để khai báo file js được dùng đến

app.IndexBook = IndexBook; mục đích để đặt name.

trong app/views/books/index.html.erb các bạn xóa hết nội dung và thêm vào cho mình

<%= react_component('app.IndexBook', books: @books) %>

Các bạn sẽ thấy ở đây, mình gửi @books sang IndexBook dưới dạng books (cái này là props)

IndexBook được viết trong './components/books/IndexBook.es6' như import ở trên. Vì vậy các bạn tạo cho mình 2 file

app/javascripts/components/books/IndexBoox.es6.js

app/javascripts/components/books/BookRow.es6.js

trong BookRow.es6.js

import React, {Component} from 'react';

class ShowBook extends Component {
  constructor(props) {
    super(props);
    this.state = {
      book: props.book
    };
  }

  render() {
    return(
      <div>
        <div>ID: {this.state.book.id}</div>
        <div>Title: {this.state.book.title}</div>
        <div>Author: {this.state.book.author}</div>
      </div>
    );
  }
}

export default ShowBook;

trong IndexBook.es6.js

import React, {Component} from 'react';
import BookRow from './bookRow.es6';

class IndexBook extends Component {
  constructor(props) {
    super(props);
    this.state = {
      books: props.books
    }
  }

  render() {
    return(
      <div>
        <table>
          <thead>
            <tr>
              <th>ID</th>
              <th>Title</th>
              <th>Author</th>
              <th></th>
              <th></th>
            </tr>
          </thead>
          <tbody>

              { this.state.books.map(
                (book) => < BookRow
                key={book.id}
                id={book.id}
                title={book.title}
                author={book.author} />
              ) }
          </tbody>
        </table>
      </div>
    );
  }
}

export default IndexBook;

Hẳn khi nhìn đoạn code trên, các bạn sẽ thấy nó khá cool và quen thuộc cũng như dễ đọc. Vì nó khá giống với Java, đều có extents, có contructor, có supper. Ý nghĩa của nhưng key words này thì cũng tương tự như bên java.

Nói thêm 1 chút. Ở đây mình dùng 2 component là IndexBook và BookRow. Trong đó IndexBook là để show table các books, còn BookRow là hiển thị mỗi book.

Đến đây thì các bạn đã hoàn tất việc setup cũng như tạo 1 ví dụ với react và rails, viết theo "xì tai" jsx + es6.

Cuối cùng thì mình có kết quả

Screen Shot 2016-06-27 at 10.11.25 PM.png

P/S: Mình mới tìm hiểu về react, nên bài viết sẽ có nhiều sai sót, các bạn cùng trao đổi và chia sẻ để cùng hiểu rõ vấn đề hơn nhé. Thanks