React Router version 4 basic example

1. Phân tích

Trong thời gian mình tìm hiểu React - Redux thì thấy React Router cũng khá hay nên quyết định viết một ví dụ nho nhỏ áp dụng React-Redux và React Router v4. Các bạn lưu ý là React Router version 4 có cách viết khá khác với React Router version 3 nhé, chi tiết có thể xem tại Guides này: (https://github.com/ReactTraining/react-router/blob/25776d4dc89b8fb2f575884749766355992116b5/packages/react-router/docs/guides/migrating.md#the-router). Bây giờ chúng ta xem sơ qua ví dụ của mình sắp viết sẽ bao gồm những phần gì: Chúng ta sẽ viết tương tự với ví dụ Tour of Heroes trong AngularJS, dựa trên cách viết của ReactJS thì đầu tiên (luôn luôn như vậy) chia nhỏ App của mình ra. Cụ thể làm 3 phần trong ví dụ này:

  • App: Component chính, chịu trách nhiệm bọc tất cả các Components khác như NavigationsMain.
  • Navigations: Component chứa các đường dẫn đến các trang khác nhau như Home, List of Heroes, About, Contact.
  • Main: Phần nội dung sẽ được hiển thị dựa trên từng Link được click trên Navigations.

Như vậy là đã xong phần phân tích sơ lược về ví dụ chúng ta cần làm. Giờ bắt đầu code nào!

2. Tạo và cài đặt App React-Redux

Nếu bạn nào lần đầu học ReactJS thì nên đọc bài này trước rồi quay lại nhé (https://viblo.asia/p/nhap-mon-react-voi-tictactoe-phan-1-OeVKBgNyZkW). Giả sử chúng ta có nền về React và Redux rồi, giờ tiến hành tạo App như sau:

create-react-app react-redux-router
cd react-redux-router
npm install --save redux # Cài redux vào các bạn nhé
npm install --save react-redux # Cài cầu nối react-redux vào
npm install --save react-router-dom # Chúng ta sẽ sử dụng react-router-dom thay vì react-router-native
subl. # Bạn nào sử dụng Atom thì atom . nhé

Chúng ta thực hiện các bước sau để cài đặt React-Redux nha:

  1. Xóa thư mục src trong react-redux-router folder vừa mới tạo xong. # Lý do vì sao xóa? - Vì trong src mặc định có rất nhiều thư mục được tạo sẵn -> Xóa cả thư mục là nhanh nhất
  2. Tạo mới thư mục src lại.
  3. Tạo mới lần lượt các thư mục: a. components b. containers c. reducers d. index.js e. actions # Trong ví dụ này không cần Action, các bạn có thể tạo cũng được mà không cũng được f. components/app.js g. reducers/index.js
  4. Thêm đoạn code sau vào src/index.js vừa tạo (Tự gõ chứ đừng copy các bạn nhé):
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux' # Có sử dụng Reducers nên cần Provider để lưu Store
import { createStore, applyMiddleware } from 'redux' # Do chúng ta có sử dụng Reducers nên phải tạo Store, còn Middleware để ngăn cho các trường hợp như actions trả về là Promise chẳng hạn.
import { BrowserRouter } from 'react-router-dom' # Sử dụng cái này để tạo Routes nhé
import App from './components/app'
import reducers from './reducers'

const createStoreWithMiddleware = applyMiddleware()(createStore)

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </Provider>,
  document.getElementById('root')
)
  1. Thêm đoạn code sau vào reducers/index.js:
import { combineReducers } from 'redux'

const rootReducer = combineReducers({
  state: (state = {}) => state
})

export default rootReducer
  1. Thêm đoạn code sau vào components/app.js:
import React from 'react'

export default () => (
  <div>
    {1 + 1} # Tạm thời để như thế này test coi được không đã
  </div>
)
  1. Chạy npm start trong Terminal và vào localhost:3000 để kiểm tra kết quả

Nếu kết quả như hình sau thì rất tốt, chúng ta đã hoàn thành xong phần cài đặt React-Redux và React Router v4

3. Bắt đầu với components và containers

Để xác định một Components là Components hay Container, ta phải xét xem Component đó có dính dáng gì với dữ liệu hay không ( hoặc Component đó theo khái niệm của React có lưu trữ state hay không).

  • App: Chỉ chịu trách nhiệm chứa hai đối tượng là Main và Navigations, do đó nó đơn thuần chỉ là một Component.
  • Navigations: Ta hình dung nó chỉ là nơi chứa các đường Link thôi mà, nên cũng không dính dáng gì tới dữ liệu -> Chỉ là Component.
  • Main: Là nơi hiển thị ra nội dung của từng Navigation được click ra -> Cũng là Component Ta tiến hành tạo các Components, Containers như đã phân tích ở trên:
  1. Thêm mới components/navigations.js:
import React from 'react'

export default () => (
  <div>
    This is Navigation
  </div>
)
  1. Thêm mới containers/main.js:
import React from 'react'

export default () => (
  <div>This is main</div>
)
  1. Thêm đoạn code sau vào App.js:
import React from 'react'
import Navigation from './navigation'
import Main from './main'

export default () => (
  <div>
    <Navigation />
    <Main />
  </div>
)

Bật browser lên và ta đạt được kết quả như sau:

4. Bắt đầu với Navigations

Theo như mockups đã đưa ra ở phần 1 thì phần Navigations gồm các Link dẫn đến những trang khác nhau. Do đó ta sẽ sử dụng <Link> của react-router-dom. Thêm phần code sau vào components/navigation.js

import React from 'react'
import { Link } from 'react-router-dom'

export default () => (
  <ul>```
    <li><Link to="/">Home</Link></li>
    <li><Link to="/heroes">List of heroes</Link></li>
    <li><Link to="/about">About</Link></li>
    <li><Link to="/contact">Contact</Link></li>
  </ul>
)

Lúc này khi click vào mỗi link trên Navigation, ta sẽ thấy URL đã được chuyển đổi nhưng nội dung thì vẫn còn nguyên như vậy: Như vậy, tạm thời phần Navigations đã xong, ta chuyển sang phần Main với mục đích hiển thị nội dung cho từng Navigation được click vào.

5. Bắt đầu với Home

Chúng ta sẽ bắt đầu với phần hiển thị khi click vào Navigation Home trước, trong components/main.js ta thêm đoạn code sau:

import React from 'react'
import { Switch, Route } from 'react-router-dom'
import Home from './home'

export default () => (
  <Switch>
    <Route exact path="/" component={Home} />
  </Switch>
)

Và tạo mới một components/home như sau:

import React from 'react'

export default () => (
  <div>Welcome to the Summoner's Rift</div>
)

Sau khi ta refresh lại trang, khi click vào Home sẽ hiển thị phần nội dung của components Home ta vừa tạo, như vậy đã xong phần hiển thị Home rồi.

#6. Bắt đầu với List of Heroes Để hiển thị danh sách các Hero thì ta cần phải có Reducers cung cấp danh sách này -> Ta cần tạo một Containers Heroes để lấy danh sách đó.

  1. Thêm đoạn code sau vào main.js
import React from 'react'
import { Switch, Route } from 'react-router-dom'
import Home from './home'
import Heroes from '../containers/heroes'

export default () => (
  <Switch>
    <Route exact path="/" component={Home} />
    <Route exact path="/heroes" component={Heroes} />
  </Switch>
)
  1. Tạo mới reducers/reducer_heroes.js:
export default () => {
  return [
    {id: '1', name: 'Vayne', class: 'AD'},
    {id: '2', name: 'Riven', class: 'TOP'},
    {id: '3', name: 'Ryze', class: 'MID'},
    {id: '4', name: 'Lee sin', class: 'Jungle'},
    {id: '5', name: 'Leona', class: 'Support'}
  ]
}
  1. Thêm reducer vừa tạo vào reducers/index.js:
import { combineReducers } from 'redux'
import HeroesReducer from './reducer_heroes'

const rootReducer = combineReducers({
  heroes: HeroesReducer
})

export default rootReducer
  1. Tạo mới containers/heroes.js:
import React, { Component } from 'react'
import { connect } from 'react-redux'

class Heroes extends Component {
  renderHeroes(hero) {
    return (
      <li key={hero.id}>
        {`ID: ${hero.id} - Name: ${hero.name} - Class: ${hero.class}`}
      </li>
    )
  }

  render() {
    return (
      <ul>
        {this.props.heroes.map(this.renderHeroes)}
      </ul>
    )
  }
}

function mapStateToProps({ heroes }) {
  return { heroes }
}

export default connect(mapStateToProps)(Heroes)

Chúng ta refresh lại trang và khi click vào Link list of heroes thì sẽ hiển thị ra danh sách các Hero đã nhận được từ Reducers:

6. Bắt đầu với About và Contact

Với About và Contact, cũng tương tự như Home, hai đối tượng này cũng đều là Component. Do đó:

  1. Thêm mới components/about:
import React from 'react'

export default () => (
  <div>This is About fage.</div>
)
  1. Thêm mới components/contact:
import React from 'react'

export default () => (
  <div>This is Contact fage.</div>
)
  1. Thêm Route cho About và Contact vào Main.js
import React from 'react'
import { Switch, Route } from 'react-router-dom'
import Home from './home'
import Heroes from '../containers/heroes'
import About from './about'
import Contact from './contact'

export default () => (
  <Switch>
    <Route exact path="/" component={Home} />
    <Route exact path="/heroes" component={Heroes} />
    <Route exact path="/about" component={About} />
    <Route exact path="/contact" component={Contact} />
  </Switch>
)

Như vậy, hiện tại chúng ta đã thoải mái click vào bất cứ Link trong Navigation nào, ví dụ cơ bản về React Router v4 đã hoàn thành. Cảm ơn các bạn đã theo dõi!