Saturday, February 27, 2021
Lưu Xuân Trường's Blog
  • Trang chủ
  • Backend
    • Laravel
    • Golang
    • NodeJS
    • MongoDB
    • Redis
    • WordPress
      • Kinh nghiệm
      • Plugins
  • Frontend
    • CSS
    • Javascript
      • ReactJS
      • UmiJS
      • VueJS
      • NuxtJS
      • Angular
      • RxJS
    • Game HTML5
  • Mobile
    • React Native
    • IOS
    • Android
    • Flutter
  • Tutorials
    • Redux-Saga
  • How to
  • Góc Ngoài Lề
    • Sống Chậm Nghĩ Sâu
    • Câu Hỏi Phỏng Vấn
    • IQ Test
  • Liên Hệ
No Result
View All Result
  • Trang chủ
  • Backend
    • Laravel
    • Golang
    • NodeJS
    • MongoDB
    • Redis
    • WordPress
      • Kinh nghiệm
      • Plugins
  • Frontend
    • CSS
    • Javascript
      • ReactJS
      • UmiJS
      • VueJS
      • NuxtJS
      • Angular
      • RxJS
    • Game HTML5
  • Mobile
    • React Native
    • IOS
    • Android
    • Flutter
  • Tutorials
    • Redux-Saga
  • How to
  • Góc Ngoài Lề
    • Sống Chậm Nghĩ Sâu
    • Câu Hỏi Phỏng Vấn
    • IQ Test
  • Liên Hệ
No Result
View All Result
Lưu Xuân Trường's Blog
No Result
View All Result

Một số tips khi làm việc với dvaJS

truongluu by truongluu
01/06/2020
in ReactJS, UmiJS
Reading Time: 8min read
0 0
0
Một số tips khi làm việc với dvaJS
0
SHARES
128
VIEWS
Share on FacebookShare on Twitter

Khi làm việc chung với kiến trúc dvaJS, mình có gặp nhiều tình huống khác nhau và bài viết này mình chia sẻ một số tips khi làm việc với dvaJS có thể nhiều bạn sẽ cần để tăng hiệu suất làm việc của mình và làm việc nó chuyên nghiệp hơn. Các bạn có thể để lại comment cho những tips bạn thấy hay nhé hoặc có tips nào hay bạn đã gặp, để mình cập nhật thêm (nếu chưa biết gì về dvaJS các bạn xem thêm bài viết về dvaJS)

  • Cách sử dụng loading model trong dvaJS.
  • Tải dữ dữ liệu khi vào 1 trang cụ thể và tải theo filter từ queries của url.
  • Put effect trong dvaJS là non blocking, vậy muốn dùng put mà đợi kết quả trả về để chạy được tác vụ khác thì sao.
  • Theo dõi effect (bắt đầu hoặc kết thúc) để làm 1 tác vụ gì đó liên quan.
  • Sử dụng call effect với các thư viện hoặc built-in chỉ hổ trợ callback.

Cách sử dụng loading model trong dvaJS

Đối với loading model mình sẽ thao tác được những gì, cụ thể như sau nhé

Loading model cung cấp cho chúng ta 3 cách để truy xuất

  1. Theo dõi trạng thái tải của toàn ứng dụng (có cái gì loading thì nó cũng thông báo)
  2. Theo dõi trạng thái tải theo model chỉ định
  3. Theo dõi trạng thái tải theo 1 effect chỉ định

Giả sử mình có 2 model là user và login như hình

model user và login có nội dung sau

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default {
  namespace: 'user',
 
  state: {
    profile: {}
  },
 
  effects: {
    *effect1(action, { call, put }) {
      
    },
    *effect2(action, { call, put }) {
      
    },
    
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default {
  namespace: 'login',
 
  state: {
    login: false
  },
 
  effects: {
    *effect1(action, { call, put }) {
      
    },
    *effect2(action, { call, put }) {
      
    },
    
  }
};

Và mình có 1 page là user.js, với mã đơn giản

1
2
3
4
5
6
7
8
9
10
import React from 'react';
import { connect } from 'dva';
 
export default (props) => {
  return (
    <div>
      <h1>User page</h1>
    </div>
  );
}

Ở page user này mình sẽ viết lại mã để theo dõi trạng thái tải toàn bộ, model cụ thể và effect cụ thể như sau

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import React from 'react';
import { connect } from 'dva';
 
export default connect(({ loading }) => ({
  globalLoading: loading.global,
  userLoading: loading.models['user'],
  loginLoading: loading.models['login'],
  effect1UserLoading: loading.effects['user/effect1']
}))((props) => {
  return (
    <div>
      <h1>User page</h1>
      <ul>
        <li>
          globalLoading: {props.globalLoading}
        </li>
        <li>
          userLoading: {props.userLoading}
        </li>
        <li>
          loginLoading: {props.loginLoading}
        </li>
        <li>
          effect1UserLoading: {props.effect1UserLoading}
        </li>
      </ul>
    </div>
  );
})

Vậy là mình đã theo dõi được những gì mình cần

Tải dữ liệu khi vào 1 trang cụ thể và tải theo filter từ queries của url

Trường hợp này các bạn hay gặp khi nào, thay vì vào 1 page cụ thể như user, các bạn sẽ vào trong hàm componentDidMount rồi gọi dispatch({type: ‘user/effect1’}) gì đó là cách mà các bạn hay làm, thì ở đây mình kiểm tra và fetch dữ liệu trong model luôn nhé.

Model cho mình theo dõi được thay đổi của pathname, và việc mình cần làm là đăng ký nó trong subscriptions, đối với model nào thì mình đăng ký ở model đó nhé (khi vào page user thì đăng ký trong subscriptions của user model chẳng hạn, hoặc các bạn có thể tổ chức tập trung hay gì đó tùy). Các bạn theo dõi đoạn mã sau trong model user nhé

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export default {
  namespace: 'user',
  ...
  subscriptions: {
    setup(history, dispatch) {
      return history.listen(({pathname}) => {
        if (pathname === '/user') {
          dispatch({
            type: 'effect1'
          });
        }
      });
    }
  }
}

Đoạn mã trên mình lắng nghe thay đổi pathname và kiểm tra nếu pathname hiện tại là /user (ứng với trang user) thì gọi effect1 để xử lý tiếp

Vậy trong trường hợp bạn đang xử lý tải dữ liệu theo url khi vào trang /user?page=1…, thì trong subscriptions, bạn cũng truy xuất được biến query và tải dữ liệu theo phân trang, xét đoạn mã bên dưới:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export default {
  namespace: 'user',
  ...
  subscriptions: {
    setup(history, dispatch) {
      return history.listen(({pathname, query}) => {
        if (pathname === '/user') {
          dispatch({
            type: 'effect1',
            payload: query
          });
        }
      });
    }
  }
}

Với đoạn mã trên thì ta truy xuất thêm được thêm tham số là query (tham số này là 1 object chưa tất cả query đang có trên url hiện tại)

Và khi xử lý mã tải dữ liệu theo trang trong subscriptions, ta cũng giải quyết luôn trường hợp là refesh lại trình duyệt và vẫn tải dữ liệu đúng theo trang và tham số query trên url

Put effect trong dvaJS là non blocking, vậy muốn dùng put và đợi kết quả trả về để chạy tác vụ khác thì sao

Thông thường các bạn thường gọi put effect để gọi tới reducer hoặc effect nào đó, nhưng có bao giờ các bạn suy nghĩ put effect đó nó sẽ chạy như thế nào, nếu nhiều nhiều put effect 1 lần thì sao có ưu tiên gì hay thứ tự nó chạy sao. Xét ví dụ bên dưới

1
2
3
4
5
6
7
yield put({
type: 'user/updateData'
})
 
yield put({
type: 'login/updateLogin'
})

Đoạn mã trên cho phép ta gọi tới 1  effect hoặc 1 reducer bên trong effect hiện tại và put này là non blocking như các bạn (non blocking là gì các bạn tham khảo thêm saga effect nhé).
Vậy nếu ở đoạn mã trên chúng ta muốn chắc chắn rằng user/updateData đã chạy hoàn thành thì mới chạy 1 put effect khác bên dưới. Đơn giản thôi nha các bạn put effect cung cấp cho chúng ta 1 chức năng đó là resolve. Viết lại đoạn mã trên

1
2
3
4
5
6
7
yield put.resolve({
  type: 'user/updateData'
})
 
yield put({
  type: 'login/updateLogin'
})

Với đoạn mã trên thì effect là user/updateData sẽ đảm bảo là chạy xong thì mới chạy đến đoạn mã bên dưới

Theo dõi effect (bắt đầu hoặc kết thúc) để làm 1 tác vụ gì đó liên quan

Tips này mình đã viết riêng ở 1 bài, các bạn theo dõi bài viết này nhé https://luuxuantruong.info/watcher-effect-trong-dvajs/

Sử dụng call effect với các thư viện hoặc built-in chỉ hổ trợ callback

Đơn giản là chuyển hàm mình cần thao tác về 1 Promise nha các bạn, vậy là chúng ta sẽ đảm bảo được call effect sẽ lấy được kết quả trả về nếu callback được gọi à. Xét trường hợp ví dụ:

Mình muốn lấy location hiện tại của trình duyệt bằng built-in function của object navigator trình duyệt bằng phương thức navigator.geolocation.getCurrentPosition (mà hàm này chỉ cung cấp callback để sử dụng), nên mình sẽ chuyển nó về 1 Promise như mã sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
export function geoFindMeEffect(maps) {
  return new Promise((resolve, reject) => {
    if (!navigator.geolocation) {
      reject(new Error('Vị trí địa lý không được hổ trợ trên trình duyệt của bạn'));
      return;
    }
    function error() {
      reject(new Error('Không thể truy xuất vị trí của bạn'));
    }
    function success(position) {
      const geocoder = new maps.Geocoder();
      geocoder.geocode(
        { location: { lat: position.coords.latitude, lng: position.coords.longitude } },
        (results, status) => {
          if (status === 'OK') {
            if (results[0]) {
              const point = {
                lat: position.coords.latitude,
                lng: position.coords.longitude,
                address: results[0].formatted_address,
              };
              return resolve(point);
            }
          }
          return reject(new Error('Không thể lấy địa chỉ hiện tại'));
        }
      );
    }
    navigator.geolocation.getCurrentPosition(success, error);
  });
}

hàm này sẽ trả về là point object nếu lấy được từ trình duyệt hoặc ném lỗi với thông báo ‘Không thể lấy được địa chỉ hiện tại’ nha các bạn

Và ở 1 effect tương ứng cần gọi thì mình gọi bình thường

1
2
3
4
5
6
7
8
9
10
11
12
13
export default {
  namespace: 'user',
  ...
  effects: {
  * getLocation(action, { call }) {
    try {
      const currentLocation = yield call(geoFindMeEffect, mapInstanceObject);
    } catch (err) {
      console.log(err);
    }
 
  },
}

Vậy là mình đã gọi tới geoFindMeEffect và đợi point trả về (trường hợp không nhận được point trả về thì bắt ngoại lệ ở catch và thông báo lỗi)

Happy coding 🙂

Tags: dvaJSreactJSumiJS
Previous Post

Chia sẻ template mẫu khi làm việc với UmiJS

Next Post

Chia sẻ một số câu hỏi phỏng vấn về kiến thức nền tảng trong Javascript

truongluu

truongluu

Next Post
Một số câu hỏi phỏng vấn frontend developer

Chia sẻ một số câu hỏi phỏng vấn về kiến thức nền tảng trong Javascript

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Don't let yesterday take up too much of today

Will Rogers

Quotations

About me

Field of interests: Svelte, ReactJS, Angular, VueJS, React Native, Flutter, NodeJS, MongoDB, Message Broker, WordPress, AdonisJS, NestJS, NuxtJS, Docker, Microservice, Arduino, Game HTML5. Hope to share my experiences with everybody

Recent Posts

  • Code push in React Native
  • What’s middleware? How does it work?
  • Styled components trong ReactJS
  • Frontity cơ bản phần I (Tạo và chạy dự án)
  • React framework for WordPress

Recent Comments

  • truongluu on Giới thiệu về UmiJS P2 (Cấu trúc thư mục, cấu hình thường dùng)
  • Hung on Giới thiệu về UmiJS P2 (Cấu trúc thư mục, cấu hình thường dùng)
  • Redux Saga phần III (Tips khi làm việc) - Lưu Xuân Trường's Blog on Quản lý trạng thái tải khi dùng redux-saga
  • Redux Saga phần II (Các khái niệm cơ bản) - Lưu Xuân Trường's Blog on Cheatsheets Non Blocking, Blocking Redux Saga
  • truongluu on Giới thiệu về UmiJS P4 (Server Side Rendering)

Archives

  • February 2021
  • January 2021
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • March 2020
  • February 2020
  • January 2020
  • June 2019
  • May 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • April 2018
  • March 2018

Categories

  • AdonisJS
  • Angular
  • Arduino
  • Backend
  • Câu Hỏi Phỏng Vấn
  • CSS
  • Ebook
  • Frontend
  • Frontity
  • Góc Ngoài Lề
  • How to
  • IOS
  • IQ Test
  • Javascript
  • Kinh nghiệm
  • Kinh nghiệm làm việc
  • Máy chủ
  • Mobile
  • MongoDB
  • NestJS
  • NodeJS
  • NuxtJS
  • Plugins
  • React Native
  • React Native
  • ReactJS
  • Redis
  • Redux-Saga
  • RxJS
  • Tutorials
  • UmiJS
  • Uncategorized
  • VueJS
  • WordPress

Friends

Phu's blog
  • RxJS toàn tập (P1 giới thiệu RxJS là gì)

    RxJS toàn tập (P1 giới thiệu RxJS là gì)

    0 shares
    Share 0 Tweet 0
  • Giới thiệu về UmiJS P1 (Tổng quan về umiJS)

    0 shares
    Share 0 Tweet 0
  • Giới thiệu về UmiJS P2 (Cấu trúc thư mục, cấu hình thường dùng)

    0 shares
    Share 0 Tweet 0
  • Redux Saga phần I (Giới thiệu)

    0 shares
    Share 0 Tweet 0
  • Một số câu hỏi phỏng vấn frontend developer

    0 shares
    Share 0 Tweet 0

About me

Lưu Xuân Trường

Field of interests: Svelte, ReactJS, Angular, VueJS, React Native, Flutter, NodeJS, MongoDB, Message Broker, WordPress, AdonisJS, NestJS, NuxtJS, Docker, Microservice, Arduino, Game HTML5. Hope to share my experiences with everybody

© 2020 https://luuxuantruong.info

No Result
View All Result
  • Trang chủ
  • Backend
    • Laravel
    • Golang
    • NodeJS
    • MongoDB
    • Redis
    • WordPress
      • Kinh nghiệm
      • Plugins
  • Frontend
    • CSS
    • Javascript
      • ReactJS
      • UmiJS
      • VueJS
      • NuxtJS
      • Angular
      • RxJS
    • Game HTML5
  • Mobile
    • React Native
    • IOS
    • Android
    • Flutter
  • Tutorials
    • Redux-Saga
  • How to
  • Góc Ngoài Lề
    • Sống Chậm Nghĩ Sâu
    • Câu Hỏi Phỏng Vấn
    • IQ Test
  • Liên Hệ

© 2020 https://luuxuantruong.info

Welcome Back!

Login to your account below

Forgotten Password?

Create New Account!

Fill the forms below to register

All fields are required. Log In

Retrieve your password

Please enter your username or email address to reset your password.

Log In