Xây dựng ứng dụng React dựa theo Redux



  • 1. Giới thiệu

    React là thư viện javascript để xây dựng ứng dụng frontend và được phát triển bởi Facebook. Ưu điểm là tăng khả năng trải nghiệm của người dùng, Facebook được làm hoàn toàn bằng React nên bạn có thể thấy khả năng ưu việt của nó.

    Redux là thư viện javascript để quản lý trạng thái state của ứng dụng. Nó có thể được tích hợp vào các app frontend được viết bằng React, Angular, hay VueJS. Ngoài Redux thì còn có thư viện Flux. Đây là 2 kiến trúc quản lý state hay dùng, tuy nhiên Redux có ưu điểm hơn là:

    • giảm bớt độ phức tạp hơn so với Flux vì loại bỏ thành phần dispatch và gắn chức năng dispatcher cho state.
    • chỉ có 1 state duy nhất , hạn chế độ phức tạp khi đồng bộ giữa các state trong flux , giúp chia sẻ code và tái sử dụng.

    Các thành phần cơ bản trong kiến trúc Redux là:

    • action
    • container
    • component
    • reducer
    • store

    Để khởi tạo ứng dụng ta sử dụng công cụ create-react-app của Facebook

        sudo npm install -g create-react-app
        create-react-app test-react-redux
    

    Cài đặt thư viện

        cd test-react-redux
        npm install --save redux react-redux
        -- react-redux có nhiệm vụ kết nối giữa react và redux
    

    Cấu trúc thư mục:

    2. Các thành phần Redux

    Actions

    Action là những đối tượng mô tả cách chúng ta muốn thay đổi state. Bạn có thể hình dung action như là những API cho state của bạn.

    VD: ta có TodoActions định nghĩa ra các thao tác thêm sửa xóa... công việc. Các action mang type và các thông tin id, text.

        // actions/TodoActions.js
        import * as types from '../constants/ActionTypes';
    
        export function addTodo(text) {
            return {
                type: types.ADD_TODO,
                text
            };
        }
    
        export function deleteTodo(id) {
            return {
                type: types.DELETE_TODO,
                id
            };
        }
    
        export function editTodo(id, text) {
            return {
                type: types.EDIT_TODO,
                id,
                text
            };
        }
    

    Note: Action trong Redux là một object mà bắt buộc phải có ít nhất 1 property là "type". Mục đích của prop Type này là để Reducer nhận biết được là Action nào. Action ngoài prop type nó còn có thể bao gồm nhiều props khác để truyền data qua Reducer.

    Reducers

    Chúng ta tạo ra các sub-reducers và một root-reducer quản lý chung, root-reducer là tham số để truyền vào khi tạo store. Reducers là các pure function hoạt động theo nguyên lý :
    (state, action) => (new state)

    Vì là pure function nên các reducers sẽ không trực tiếp thay đổi state mà nó nhận được, mà tạo ra các bản copy và thay đổi trên đó. Để thực hiện điều này chúng ta có thể dùng các function filter() map() Object.assign()

        // reducers/todosReducers.js
        import { ADD_TODO, DELETE_TODO, EDIT_TODO, MARK_TODO, MARK_ALL, CLEAR_MARKED } from '../constants/ActionTypes';
    
        const initialState = [{
            text: 'Use Redux',
            marked: false,
            id: 0
        }];
    
        export default function todos(state = initialState, action) {
            switch (action.type) {
                case ADD_TODO:
                    return [{
                        id: (state.length === 0) ? 0 : state[0].id + 1,
                        marked: false,
                        text: action.text
                    }, ...state];
    
                case DELETE_TODO:
                    return state.filter((todo) => todo.id !== action.id);
    
                case EDIT_TODO:
                    return state.map((todo) => todo.id === action.id ? { ...todo, text: action.text } : todo);
    
                default:
                    return state;
            }
        }
    

    Root-reducer sẽ tập hợp các sub-reducers lại thông qua combineReducers() của Redux.

        // reducers/rootReducers.js
        import { combineReducers } from 'redux';
        import todosReducers from './todosReducers';
    
        const rootReducer = combineReducers({
            todosReducers
        });
    
        export default rootReducer;
    

    Containers

    Chúng ta có 1 container là TodoApp:

        // containers/TodoApp.js
        import React, { Component } from 'react';
        import { connect } from 'react-redux';
        import { bindActionCreators } from 'redux';
        import Header from '../components/Header';
        import MainSection from '../components/MainSection';
        import * as TodoActions from '../actions/TodoActions';
    
        class TodoApp extends Component {
            render() {
                const { todos, actions } = this.props;
    
                return (
                    <div>
                        <Header addTodo={actions.addTodo} />
                        <MainSection todos={todos} actions={actions} />
                    </div>
                );
            }
        }
    
        function mapStateToProps(state) {
            return {
                todos: state.todosReducers
            };
        }
    
        function mapDispatchToProps(dispatch) {
            return {
                actions: bindActionCreators(TodoActions, dispatch)
            };
        }
    
        export default connect(mapStateToProps, mapDispatchToProps)(TodoApp);
    

    Component

    Component thông thường, chúng không giao tiếp với Redux, chỉ nhận giá trị và thao tác thông qua props.

    Các xử lý hiển thị dữ liệu sẽ thực thi ở đây và các action nhận được từ container sẽ sử dụng như callback.

    Store

    Chúng ta sử dụng hàm createStore() với tham số là root-reducer

        import { createStore } from 'redux';
        import rootReducer from './reducers/rootReducer';
    
        // initialState
        const initialState = {}
    
        // Create store
        const store = createStore(rootReducer, initialState);
    

    Khởi tạo Root Component

    App sử dụng Redux root component đảm nhận thêm việc khởi tạo store và bao các component lại với Provider của react-redux giúp component có thể giao tiếp với redux.

        // index.js
        import 'todomvc-app-css/index.css';
        import React from 'react';
        import ReactDOM from 'react-dom';
        import { createStore } from 'redux';
        import { Provider } from 'react-redux'
        import TodoApp from './containers/TodoApp';
        import rootReducer from './reducers/rootReducer';
    
        // initialState
        const initialState = {}
    
        // Create store
        const store = createStore(rootReducer, initialState);
    
        const appRoot = (
            <Provider store={store}>
                <div>
                    <TodoApp />
                </div>
            </Provider>
        )
    
        ReactDOM.render(appRoot, document.getElementById('root'))
    

    Nguồn: Viblo


Hãy đăng nhập để trả lời
 

Có vẻ như bạn đã mất kết nối tới LaptrinhX, vui lòng đợi một lúc để chúng tôi thử kết nối lại.