Làm quen với Redux trong rails app.
Bài đăng này đã không được cập nhật trong 3 năm
Để bắt đầu với redux, bạn cần biết:
Redux là một thư viện do chính Facebook tạo ra, nó đc Facebook định nghĩa là: "predictable state container for JavaScript apps" (tạm dịch là một lớp quản lý state cho ứng dụng Javascript) , như vậy redux sẽ lưu tất cả state đc định nghĩa vào 1 nơi để bạn sử dụng.
Để sử dụng redux, bạn cần cài nó qua npm. Với rails 5.1, bạn có tùy chọn để sử dụng webpack (từ gem webpacker ) bằng option --webpack
.
Khởi tạo
rails new RedditRails --webpack=react -d mysql
(--webpack=react
= rails webpacker:install:react = npm install react react-dom)
Project RedditRails đc khởi tạo và sử dụng webpack làm assets bundler, từ đây bạn có thể sử dụng npm hoặc yarn để cài đặt các module. Trỏ đến thư mục gốc của dự án để cài đặt redux và add vào yarn lock:
cd RedditRails/
sudo npm install --save react-redux && sudo yarn add redux@^2.0.0
Tạo Index controller và sử dụng React là View chính.
//app/javascript/packs/application.js
console.log('Hello World from Webpacker')
//app/views/index/index.html.erb
<%= javascript_pack_tag "application" %> // application ở thư mục app/javascript/components
Khởi động rails server và webpack bằng 2 terminal riêng biệt
rails server
và ./bin/webpack-dev-server
Kết quả:
Bắt đầu từ đây, chúng ta sẽ sử dụng ReactJS View chính trong rails.
Các khái niệm cơ bản trong Redux
- Actions
- Actions là payload của data, redux action sẽ gửi data đến reducer để lưu vào store.
- Actions là JavaScript objects, nó phải có property
type
để nhận biết action nào đang được thực hiện. - Luôn sử dụng action để thay đổi state.
- Reducer
- Actions mô tả những hành động đã xảy ra nhưng nó không thay đổi state khi nhận đc kết quả => sử dụng reducer để thay đổi state.
- Reducer phải là Pure function
- Store
- Store là object chứa state của toàn bộ ứng dụng.
- Cho phép lấy state bằng method
getState()
- Update state bằng việc dispatch một action
dispatch(action)
- Subscribe listener qua method
subscribe(listener)
- Handle các listener chưa đăng kí bằng return của
subscribe(listener)
- Chỉ có duy nhất một store trong một ứng dụng redux, nếu bạn muốn quản lý logic cho data hãy sử dụng reducer.
- Data flow trong redux:
Như vậy để xử lý data trong redux, đầu tiên bạn cần biết payload của một action là gì, sau đó xử lý logic trong Reducer, phần việc còn lại reducer sẽ lưu các state con vào 1 state cha.
Khai báo redux trong rails
Trong thư mục app/javascript
tạo các folder: actions
, components
, constants
, reducers
, stores
. Mỗi folder sẽ lưu từng file thành phần tương ứng.
Như đã nói ở trên, redux luôn sử dụng action để handle state. Vì vậy chúng ta sẽ khởi tạo action trước. Có action thì mới có data, có data thì ta mới dùng reducer xử lý data và lưu vào state đc.
Tạo action
//actions/hello_action.js
export const helloAction = (text) => {
return {
type: 'SAY_HELLO',
payload: text
}
}
export default helloAction
Tạo reducer
//reducers/hello_reducer.js
export default const helloReducer = (state = [], action) => {
switch(action.type) {
case 'SAY_HELLO':
const { text } = action.payload
return text
default:
return state
}
}
Tạo demo component
//components/App.js
import React from 'react'
import { connect } from 'react-redux'
import { helloAction } from '../actions/hello_action'
import { bindActionCreators } from 'redux'
class App extends React.Component {
constructor(props) {
super(props);
this.sayHi = this.sayHi.bind(this)
}
sayHi(e) {
const { value } = e.target
const { helloAction } = this.props
helloAction(value)
}
render() {
const { text } = this.props
return(
<div>
<h1>Type anything to say hi ^^ </h1>
<h3>{text || "just a dummy h3"}</h3>
<input type="text" onChange={(e) => this.sayHi(e)} />
</div>
)
}
}
// lấy text payload từ redux store truyền vào props của App component
const mapStateToProps = state => {
const { text } = state
return { text }
}
// lấy ra action helloAction gán vào props của App component
const mapDispatchToProps = dispatch => {
return {
helloAction: (text) => {
dispatch(helloAction(text))
}
}
}
// connect component App đến Redux store.
App = connect(
mapStateToProps,
mapDispatchToProps
)(App)
export default App
Khai báo redux store
//application.js
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux';
import { createStore } from 'redux'
import helloReducer from './reducers/hello_reducer';
import App from './components/App'
let store = createStore(helloReducer);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
Kết quả
Như vậy chúng ta vừa tạo ra 1 page đơn giản sử dụng Rails + react-redux. Github của tutorial: https://github.com/nguyenthetoan/RedditRails
Ở bài viết tiếp theo, chúng ta sẽ sử dụng redux với Reddit API.
All rights reserved