hocvietcode.com
  • Trang chủ
  • Học lập trình
    • Lập trình C/C++
    • Lập trình HTML
    • Lập trình Javascript
      • Javascript cơ bản
      • ReactJS framework
      • AngularJS framework
      • Typescript cơ bản
      • Angular
    • Lập trình Mobile
      • Lập Trình Dart Cơ Bản
        • Dart Flutter Framework
    • Cơ sở dữ liệu
      • MySQL – MariaDB
      • Micrsoft SQL Server
      • Extensible Markup Language (XML)
      • JSON
    • Lập trình PHP
      • Lập trình PHP cơ bản
      • Laravel Framework
    • Lập trình Java
      • Java Cơ bản
    • Cấu trúc dữ liệu và giải thuật
    • Lập Trình C# Cơ Bản
    • Machine Learning
  • WORDPRESS
    • WordPress cơ bản
    • WordPress nâng cao
    • Chia sẻ WordPress
  • Kiến thức hệ thống
    • Microsoft Azure
    • Docker
    • Linux
  • Chia sẻ IT
    • Tin học văn phòng
      • Microsoft Word
      • Microsoft Excel
    • Marketing
      • Google Adwords
      • Facebook Ads
      • Kiến thức khác
    • Chia sẻ phần mềm
    • Review công nghệ
    • Công cụ – tiện ích
      • Kiểm tra bàn phím online
      • Kiểm tra webcam online
Đăng nhập
  • Đăng nhập / Đăng ký

Please enter key search to display results.

Home
  • ReactJS
Giới thiệu Redux và quản lý state với Redux trong React

Giới thiệu Redux và quản lý state với Redux trong React

  • 17-11-2022
  • Toanngo92
  • 0 Comments

Redux là một thư viện phổ biến cho các ứng dụng JavaScript và React . Nó tuân theo một nguyên tắc trung tâm rằng ràng buộc dữ liệu phải chảy theo một hướng và phải được lưu trữ như một nguồn tin cậy duy nhất. Redux đã trở nên phổ biến vì sự đơn giản của ý tưởng thiết kế và việc triển khai tương đối nhanh.

Redux hoạt động theo một vài khái niệm. Đầu tiên, store là một đối tượng duy nhất với các trường cho mỗi lựa chọn dữ liệu. Bạn cập nhật dữ liệu bằng cách thực hiện một action cho biết dữ liệu sẽ thay đổi như thế nào. Sau đó, bạn diễn giải các hành động và cập nhật dữ liệu bằng cách sử dụng reducer . Reducers là các hàm áp dụng các hành động cho dữ liệu và trả về một state mới , thay vì thay đổi state trước đó.

Trong các ứng dụng nhỏ, bạn có thể không cần kho dữ liệu toàn cục. Bạn có thể sử dụng kết hợp giữa state và context cục bộ để quản lý state. Nhưng khi ứng dụng của bạn mở rộng quy mô, bạn có thể gặp phải các tình huống mà việc lưu trữ thông tin một cách tập trung sẽ có giá trị để thông tin sẽ tồn tại trên các routes và components . Trong tình huống đó, Redux sẽ cung cấp cho bạn một giải pháp chuẩn xác để lưu trữ và truy xuất dữ liệu một cách có tổ chức.

Mục lục

  • Khởi tạo dự án và cài đặt redux
  • Khởi tạo dự án bằng redux toolkit theo cách tiếp cận chuẩn

Khởi tạo dự án và cài đặt redux

npx create-react-app reactreduxdemo
cd reactreduxdemo
npm install react-jss
npm install react-proptypes
npm install --save redux react-redux

Bắt đầu dự án, chúng ta tiến hành bọc component Provider cho ứng dụng bằng cách sửa file src/index.js:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider>
      <App />
    </Provider>
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Bây giờ bạn đã bọc các component của mình, chúng ta bắt đầu thêm một store. Store là danh sách dữ liệu trung tâm của bạn. Tiếp tục sửa file index.js như sau:

import React, { useReducer } from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App1';
import reportWebVitals from './reportWebVitals';
import { Provider } from 'react-redux';
import {createStore} from 'redux';

const root = ReactDOM.createRoot(document.getElementById('root'));

const store = createStore(() => ({

}));

root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Giải thích: ở đây mình dùng hàm createStore để tạo một store toàn cục cho ứng dụng. Với tình huống này mình truyền vào hàm callback bên trong createstore là một object rỗng.

Mình sẽ thêm một vài thuộc tính vào trong object này:

import React, { useReducer } from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { Provider } from 'react-redux';
import {createStore} from 'redux';

const root = ReactDOM.createRoot(document.getElementById('root'));

const store = createStore(() => ({
  testvalue: {
    id: 1,
    value: 'hello'
  }
}));

root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Sửa file App.js

import React from 'react';
import { useSelector } from 'react-redux';


function App() {

  const testvalue = useSelector(state => state.testvalue);
  console.log(testvalue);
  return (null);
}

export default App;

Output:

Chúng ta thấy, ở bên trong App component có thể truy cập được vào giá trị trong store, lấy ra sử dụng mà không cần thông qua Context hay props nào, khá tiện. Tương tự với context, mọi component con sẽ có thể truy cập vào store mà không cần bất kỳ props bổ sung nào. Để truy cập các mục trong store Redux của bạn, sử dụng Hook được gọi useSelector từ package react-redux. useSelector Hook nhận một hàm selector làm đối số truyền vào. Hàm selector sẽ nhận trạng thái store của bạn dưới dạng đối số mà bạn sẽ sử dụng để trả về trường bạn muốn.

Khởi tạo dự án bằng redux toolkit theo cách tiếp cận chuẩn

Hầu hết các bài hello world từ phiên bản cũ đều sử dụng createStore, tuy nhiên đây là cách không đưược recommend, chúng ta chỉ hellowold cho biết, ở dưới đây mình sẽ tiếp tục bắt đầu một tính năng phức tạp hơn một chút, dựa theo quickstart của ReactJS.

Xem thêm tại: https://react-redux.js.org/tutorials/quick-start

Bước 1: cài đặt react @reduxjs/toolkit:

npm install @reduxjs/toolkit react-redux

Bước 2: tạo file src/app/store.js

import { configureStore } from '@reduxjs/toolkit'

export default configureStore({
  reducer: {},
})

Giải thích: khởi tạo configStore với reducer mặc định là một object rỗng.

Tạo file index.js và đưa biến store được import từ configStore vào, tương tự bên trên, chúng ta cũng phải import Provider để bọc <App/> Component lại:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import store from './app/store'
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </Provider>

);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Bước 3: tạo file feature/counterSlide.js nội dung như sau

// reducer

import { createSlice } from "@reduxjs/toolkit";

export const counterSlice = createSlice({
    name: 'counter',
    initialState: {
        value: 0,
    },
    reducers: {
        increment: (state) => {
            state.value +=1;
        },
        decrement: (state) =>{
            state.value -=1;
        }
    }
})

export default counterSlice.reducer

export const {increment, decrement} = counterSlice.actions

Theo tài liệu mô tả, việc tạo một slice yêu cầu một tên chuỗi để xác định tên slice, một giá trị state ban đầu và một hoặc nhiều hàm rút gọn để xác định cách cập nhật state. Khi một slice được tạo, chúng ta có thể xuất hàm reducer vaf các trình tạo hành động Redux(Redux action creators) sẽ tự động tạo cho chúng ta các method actionCreator cho toàn bộ slice.

Redux yêu cầu viết code cập nhật trạng thái một cách bất biến, bằng cách tạo các bản sao dữ liệu và cập nhật các bản sao đó. Tuy nhiên, Redux Toolkit createSlice và createReducer sử dụng immer giúp chúng ta viết logic cập nhật “đột biến” để trở thành các bản cập nhật bất biến chính xác.

Mô phỏng khi log giá trị counterSlice:

Giải thích: chúng ta thấy hàm createSlice được import từ reduxjs toolkit, chúng tao tạo một object counterSlice với các thuộc tính name,initialState và reducer. 3 phương thức increment(), decrement() và incrementByAmount() được destructure và xuất ra, 3 phương thức này là actionCreator(), được tự động tạo từ 3 reducer mới định nghĩa phía trên, đừn nhầm lẫn điều này, và reducer của counterSlice cũng được xuất ra nhằm mục đích đưa vào component sử dụng.

Xem thêm: khác biệt giữa export default và export const:

https://stackoverflow.com/questions/33611812/export-const-vs-export-default-in-es6

Bước 4: sửa file app/store.js, ở bước này chúng ta import hàm reducer từ counter slice và đưa vào trong store. Bằng cách định nghĩa trước bên trong tham số reducer, chúng ta nói với store rằng sẽ sử dụng hàm reducer của slice counter để xử lý toàn bộ state.

//store -> add reducer to store herer

import { configureStore } from "@reduxjs/toolkit";
import counterReducer from '../feature/counter/counterSlice'

export default configureStore({
    reducer: {
        counter: counterReducer
    },
})

Bước 4: tạo React Component src/feature/counter/Counter.js để bắt đầu sử dụng Redux State và Actions:

//counter component
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { increment,decrement } from "./counterSlice";

export function Counter(){
    const count = useSelector((state) => state.counter.value)
    const dispatch = useDispatch()
    // khi gap su kien onclick, ham dispatch (gui di) se goi toi cho reducer chay vao ham increment()
    return (
        <>
            <div>
                <button onClick={() => dispatch(increment())}>Increment value</button>
            </div>
            increment
            <span>{count}</span>
            <button onClick={() => dispatch(decrement())}>
                Decrement value
            </button>
        </>
    )
}

Bước 5: sửa file App.js thêm component Counter:

import logo from './logo.svg';
import './App.css';
import { Counter } from './feature/counter/Counter';

function App() {
  return (
    <div className="App">
      <Counter></Counter>
    </div>
  );
}

export default App;

Output:

Bước tiếp theo, chúng ta tiếp tục phát triển demo với tính năng số theo giá trị từ input, tăng số sử dụng Async.

Bước 6: bổ sung thêm vài phương thức bên trong file src/counter/counterSlice.js

// reducer

import { createSlice } from "@reduxjs/toolkit";

export const counterSlice = createSlice({
    name: 'counter',
    initialState: {
        value: 0,
    },
    reducers: {
        increment: (state) => {
            state.value +=1;
        },
        decrement: (state) =>{
            state.value -=1;
        },
        incrementByAmount: (state,action) => {
            console.log(state.value);
            console.log(action);
            state.value += action.payload
            console.log("state after:"+state.value)
        },

    }
})

export default counterSlice.reducer

export const {increment, decrement, incrementByAmount} = counterSlice.actions

// hàm tăng giá trị bất đồng bộ
export const incrementAsync = (amount) => (dispatch) => {
    setTimeout(() => {
      dispatch(incrementByAmount(amount))
    }, 1000)
}

// export selectCount giúp lấy giá trị nhanh hơn trong component Counter thông qua useSelector(selectCount)
export const selectCount = (state) => state.counter.value

Bước 7: sửa component src/feature/counter/Counter.js và component src/feature/counter/Counter.css

//counter component
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { increment,decrement, selectCount,incrementByAmount, incrementAsync } from "./counterSlice";

export function Counter(){
    // lay count truc tiep tu selectCount trong counterSlice
    const count = useSelector(selectCount)
    // khai bao dispatch
    // khi gap su kien onclick, ham dispatch (gui di) se goi toi cho reducer chay vao ham increment()
    const dispatch = useDispatch()
    // dinh nghia thuoc tinh incrementAmount cho state va phuong thuc setInCrementAmount de cap nhat gia tri moi cho state
    const [incrementAmount,setInCrementAmount] = useState('10');
    return (
        <>
            <div>
                <button onClick={() => dispatch(increment())}>Increment value</button>
            </div>
            increment
            <span>{count}</span>
            <button onClick={() => dispatch(decrement())}>
                Decrement value
            </button>
          <div>
          <input value={incrementAmount} onChange={(e) => setInCrementAmount(e.target.value)} />
          <button onClick={() => dispatch(incrementByAmount(parseInt(incrementAmount)))}>Increment Amount</button>
          <button onClick={() => dispatch(incrementAsync(incrementAmount))}>Increment by Amount Async</button>
          </div>
        </>
    )
}
.asyncButton{
    position: relative;
}
.asyncButton:after {
    content: "";
    background-color: rgba(112, 76, 182, 0.15);
    display: block;
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    opacity: 0;
    transition: width 1s linear, opacity 0.5s ease 1s;
  }
  
  .asyncButton:active:after {
    width: 0%;
    opacity: 1;
    transition: 0s
  }

Output:

Bài viết liên quan:

useMemo trong ReactJS
Định tuyến trong ứng dụng React với React Router
Gọi API trong React với useEffect Hook
Xử lý tải dữ liệu bất đồng bộ (Async Data Loading), lazyload trong React
Xử lý Form (biểu mẫu) trong React
Xử lý các sự kiện trong DOM và Window bằng React
Debug (gỡ lỗi) React component thông qua React Developer Tools
khái niệm React Context và chia sẻ state qua các component với React Context
Cách quản lý state(trạng thái) bằng Hooks trên React Component
React strict mode (chế độ phát triển) trong React
Quản lý state (trạng thái) trong React Class Component
Hướng dẫn định kiểu (style) cho React Component

THÊM BÌNH LUẬN Cancel reply

Dịch vụ thiết kế Wesbite

NỘI DUNG MỚI CẬP NHẬT

2. PHÂN TÍCH VÀ ĐẶC TẢ HỆ THỐNG

1. TỔNG QUAN KIẾN THỨC THỰC HÀNH TRIỂN KHAI DỰ ÁN CÔNG NGHỆ THÔNG TIN

Hướng dẫn tự cài đặt n8n comunity trên CyberPanel, trỏ tên miền

Mẫu prompt tạo mô tả chi tiết bối cảnh

Một số cải tiến trong ASP.NET Core, Razor Page, Model Binding, Gabbage collection

Giới thiệu

hocvietcode.com là website chia sẻ và cập nhật tin tức công nghệ, chia sẻ kiến thức, kỹ năng. Chúng tôi rất cảm ơn và mong muốn nhận được nhiều phản hồi để có thể phục vụ quý bạn đọc tốt hơn !

Liên hệ quảng cáo: [email protected]

Kết nối với HỌC VIẾT CODE

© hocvietcode.com - Tech888 Co .Ltd since 2019

Đăng nhập

Trở thành một phần của cộng đồng của chúng tôi!
Registration complete. Please check your email.
Đăng nhập bằng google
Đăng kýBạn quên mật khẩu?

Create an account

Welcome! Register for an account
The user name or email address is not correct.
Registration confirmation will be emailed to you.
Log in Lost your password?

Reset password

Recover your password
Password reset email has been sent.
The email could not be sent. Possible reason: your host may have disabled the mail function.
A password will be e-mailed to you.
Log in Register
×