Nay mình sẽ nói về Redux được dùng trong React. Tôi nghĩ về Redux thì đối với mấy bạn viết ứng dụng giỏ hàng chắc cũng biết về nó rồi!
Redux là gì? redux là một thư viện giúp ta quản lý State của data. Data được lưu trữ ở một Store và rồi các thành phần Component nó chạy vô Store và lấy dữ liệu ra dùng thôi.
VD: Đơn giản hơn là, nếu bạn không dùng Redux. Nếu bạn muốn lấy dữ liệu thì bạn phải request lên Server để lấy về mỗi lần! vậy là rất nhiều request đến Server, có một số bạn lưu nó ở dưới storage đễ quản lý đó là phương pháp rất hay
Còn nếu dùng Redux, thì bạn chỉ request một lần sao đó, các Component chỉ trỏ tới nơi lưu trữ Data và lấy ra thôi, nó quản lý State của các Component, đa phần bạn thấy nhiều nhất là trong quản lý Cart
Tôi sẽ nói với mấy bạn thêm một vấn đề là! Nếu dùng Redux quản lý State thì mỗi lần bạn refresh lại trang, nó sẽ bị mất! Để cho nó không bị mất State thì bạn có thể lưu nó dưới storage, và khi người dùng refresh trang, bạn sẽ xác nhận móc storage ra sử dụng!
Trong Redux ta cần phải hiểu các vấn đề sau:
+ Action: Chúng ta cũng biết toàn bộ ứng dụng được lưu trong Store, vì thế Action dùng để chứa các hành động, khi cần xử lý một thay đổi hành động nào đó , vd: hành động (CREATE,UPDATE,DELETE,...), thì tại Component cần gọi, ta cần chỉ rõ hành động cần thực thi Action đó, để thay đổi State
+ Store : Nó là một lớp dữ liệu chứa toàn bộ các phép tính và logic nghiệp vụ. Nó cũng chịu trách nhiệm lưu trữ trạng thái ứng dụng và nguồn duy nhất cho trạng thái ứng dụng. Nó nhận hành động từ người dùng điều phối! dựa trên các cuộc gọi lại đã đăng ký.
+ Reducers: dùng chỉ định cách trạng thái(State) của ứng dụng thay đổi theo các hành động(Action) được gửi đến cửa hàng(Store), chúng ta hãy nhớ các hành động chỉ mô tả những gì đã xảy ra thôi, nhưng nó không mô tả cách trạng thái của ứng dụng thay đổi.
Ok còn nhiều thứ lắm, bạn phải thực hiện nhiều ví dụ để hiểu sâu hơn, lý thuyết thì trên mạng nói rất nhiều, có nhiều người nhìn nhận một cách khác nhau, nên ta hãy làm ví dụ để tự mình hiểu thế nào nhé!
Demo:
Tạo project name "create-react-redux"
npx create-react-app create-react-redux npm install redux npm install react-redux npm install redux-thunk
Create Action Redux
Chúng ta cấu hình thư mục như sau:
+ src/components/actions/index.js: chứ các hành động xử lý thay đổi của State
export const INCREMENT = 'INCREMENT'; export const DECREMENT = 'DECREMENT'; export function fc_increment(){ return{ type:'INCREMENT' } } export function fc_decrement(){ return { type:'DECREMENT' } }
Ta tạo 2 hàm (fc_increment , fc_decrement) dùng để thực thi hành động thay đổi State
Create Reducers Redux
+ src/components/reducers/index.js : Ta cần phải chỉ định kiểm tra các trạng thay đổi tương ứng theo hành động (Action)
import {combineReducers} from 'redux'; import {INCREMENT, DECREMENT} from '../actions' const initApp= { count:0 } function fc_app(state = initApp,action){ console.log(action) switch(action.type){ case INCREMENT:{ return{ count:state.count+1 } } case DECREMENT:{ return{ count:state.count-1 } } default: return state; } } const reduxApp = combineReducers({ dataApp : fc_app }) export default reduxApp;
Đoạn code trên ta cần import file cấu hình Action vào:
import {INCREMENT, DECREMENT} from '../actions'
Khởi tạo biến lưu dữ liệu
const initApp= { count:0 }
Kiểm tra action.type đang được chỉ định là Action nào ta cần sử sụng switch để kiểm tra
function fc_app(state = initApp,action){ console.log(action) switch(action.type){ case INCREMENT:{ return{ count:state.count+1 } } case DECREMENT:{ return{ count:state.count-1 } } default: return state; } }
Sử dụng combineReducers để có thể sử dụng multiple reducer
const reduxApp = combineReducers({ dataApp : fc_app })
Create Store Redux
+ src/components/stores/index.js
import { createStore, applyMiddleware } from 'redux'; import thunkMiddleware from 'redux-thunk' import reduxApp from '../reducers' const store = createStore(reduxApp,applyMiddleware(thunkMiddleware)); export default store;
Create Component React
+ src/components/header/Header.js
import React, { Component } from 'react' import {connect} from 'react-redux' export class Header extends Component { constructor(props) { super(props) this.state = { } } componentDidMount(){ console.log(this.props.count) } render() { const {count} = this.props.count; if(count>0){ return ( <div className="header"> <h2>Count : {count}</h2> </div> ) } return ( <div className="header"> <h2>Count :0</h2> </div> ) } } const mapStateToProps = state => { return { count: state.dataApp }; }; export default connect(mapStateToProps,null)(Header);
Để móc được dử liệu trong Store, ta cần import thư viện
import {connect} from 'react-redux'
Sau đó ta dụng mapStateToProps được hổ trợ trong Redux để có thể móc dữ liệu trong Store ra
const mapStateToProps = state => { return { count: state.dataApp }; }; export default connect(mapStateToProps,null)(Header);
+ src/components/home/Home.js: ta tạo component Home.js đùng để chỉ rỏ Action, nói chung là thực thi hàm (fc_increment, fc_decrement) trong Action để có thể thay đổi State
import React, { Component } from 'react' import {connect} from 'react-redux' import {fc_increment,fc_decrement} from '../actions' export class Home extends Component { constructor(props) { super(props) } render() { return ( <div> <button onClick={()=>this.props.Decrement()}>Decrement</button> <button onClick={()=>this.props.Increment()}>Increment</button> </div> ) } } function mapDispatchToProps(dispatch) { return { Increment: () => dispatch(fc_increment()), Decrement: () => dispatch(fc_decrement()) }; } export default connect(null,mapDispatchToProps)(Home)
Code trên ta cần import thư viện Redux như sau:
import {connect} from 'react-redux'
Thêm các action cần thự thi fc_increment, fc_decrement vì thế ta cần import action
import {fc_increment,fc_decrement} from '../actions'
Sử dụng mapDispatchToProps để dispatch hai hàm trong Action
function mapDispatchToProps(dispatch) { return { Increment: () => dispatch(fc_increment()), Decrement: () => dispatch(fc_decrement()) }; } export default connect(null,mapDispatchToProps)(Home)
Ok, giờ ta cần tạo các nút để người dùng click vào để thay đổi State
<button onClick={()=>this.props.Decrement()}>Decrement</button> <button onClick={()=>this.props.Increment()}>Increment</button>
Bây giờ chúng chỉnh sửa lại App.js trong thư mục src, để gọi component (Home.js, Header.js)
import React from 'react'; import './App.css'; import Header from './components/header/Header'; import Home from './components/Home/Home'; function App() { return ( <div className="App"> <Header /> <Home /> </div> ); } export default App;
Bước quan trọng cuối cùng là ta cần cấu hình lại file index.js trong thư mục src, để có thể sử dụng Redux
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import {Provider} from 'react-redux'; import store from './components/stores' ReactDOM.render( <Provider store = {store}> <App /> </Provider>, document.getElementById('root') );
Ok, vậy là xong, giờ ta khởi động ứng dụng lên chạy xem
npm start