aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh hoạ FlatList hiển thị danh sách bài viết trong React Native

React Native RefreshControl: giữ refreshing đúng vòng đời của lượt tải

Suong Nguyen by Suong Nguyen
30/10/2026
in React Native
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Bạn kéo danh sách để tải lại, spinner vừa xuất hiện đã tắt hoặc lại quay mãi sau một lỗi. RefreshControl không tự biết Promise tải dữ liệu đã hoàn tất. Nó hiển thị theo prop refreshing do component của bạn quản lý.

Bài đối chiếu React Native 0.88 ngày 30/10/2026. Ví dụ dùng JavaScript/JSX, dữ liệu giả trong bộ nhớ và một độ trễ minh họa; không gọi server. Phần điều phối Promise được kiểm tra riêng trên Node.js 24.18.1, còn JSX đã rà API nhưng chưa build hoặc thử thao tác kéo trên Android/iOS.

Chốt hợp đồng của refreshing

RefreshControl reference ghi refreshing là controlled prop. Khi bắt đầu xử lý onRefresh, cần cập nhật nó thành true; khi công việc kết thúc, đưa nó về false. Đừng giả định khai báo async cho onRefresh khiến component native tự theo dõi Promise.

State phục vụ render, còn ref có thể giữ một cờ thay đổi ngay trong handler mà không cần chờ lần render mới. Trong ví dụ, busy ngăn lượt refresh thứ hai trong khi lượt đầu còn chạy. Nó không phải khóa ở server hoặc cơ chế bảo đảm idempotency nghiệp vụ.

Tạo một lượt tải giả có cả thành công và lỗi

async function loadDemo(shouldFail) {
  await new Promise(resolve => setTimeout(resolve, 500));
  if (shouldFail) throw new Error('Lỗi giả lập');
  return [{id: 'demo', title: 'Dữ liệu đã được tải lại'}];
}

500 là độ trễ được đặt để dễ quan sát demo, không phải số đo mạng. Hàm luôn trả cùng một bộ dữ liệu nhỏ khi thành công. Khi đưa vào app thật, thay bằng hàm tải của dự án và giữ chính sách lỗi rõ ràng.

Đặt cleanup vào finally

Đặt loadDemo ở trên trong cùng file với component dưới đây. Nút đầu màn hình đổi chế độ lỗi cho lần kéo tiếp theo, giúp kiểm tra hai nhánh mà không cần làm hỏng endpoint thật.

import React, {useEffect, useRef, useState} from 'react';
import {Button, FlatList, RefreshControl, Text, View} from 'react-native';

export default function RefreshDemo() {
  const [items, setItems] = useState([]);
  const [refreshing, setRefreshing] = useState(false);
  const [error, setError] = useState('');
  const [shouldFail, setShouldFail] = useState(false);
  const busy = useRef(false);
  const active = useRef(true);

  useEffect(() => {
    active.current = true;
    return () => { active.current = false; };
  }, []);

  async function onRefresh() {
    if (busy.current || !active.current) return;
    busy.current = true;
    setRefreshing(true);
    setError('');
    try {
      const next = await loadDemo(shouldFail);
      if (active.current) setItems(next);
    } catch (_) {
      if (active.current) setError('Tải lại chưa thành công. Bạn có thể thử lại.');
    } finally {
      busy.current = false;
      if (active.current) setRefreshing(false);
    }
  }

  return (
    <View style={{flex: 1, padding: 16}}>
      <Button
        title={shouldFail ? 'Đang mô phỏng lỗi: tắt' : 'Bật mô phỏng lỗi'}
        onPress={() => setShouldFail(value => !value)}
      />
      {error !== '' && <Text accessibilityLiveRegion="polite">{error}</Text>}
      <FlatList
        style={{flex: 1}}
        contentContainerStyle={{flexGrow: 1, paddingVertical: 16}}
        data={items}
        keyExtractor={item => item.id}
        renderItem={({item}) => <Text>{item.title}</Text>}
        ListEmptyComponent={<Text>Chưa có dữ liệu. Kéo xuống để tải thử.</Text>}
        refreshControl={
          <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
        }
      />
    </View>
  );
}

Finally chạy sau cả nhánh thành công lẫn lỗi, nên cờ busy được mở lại. Nếu component đã unmount, code không cập nhật state của nó; điều này chỉ bỏ qua kết quả muộn, không hủy Timer hoặc request đang chạy.

useRef giải thích ref phù hợp cho giá trị không dùng trực tiếp để render. useEffect mô tả cleanup khi component được gỡ và vòng kiểm tra bổ sung trong development. Đừng dùng cờ active làm bằng chứng đã cancel công việc bên dưới.

Kiểm tra thành công, lỗi và lượt chồng nhau

Ở chế độ thành công, kéo từ đầu danh sách: kiểm tra indicator được điều khiển trong thời gian chờ và dữ liệu xuất hiện sau khi hoàn tất. Bật mô phỏng lỗi rồi kéo lại: dữ liệu cũ cần được giữ, lỗi hiện bằng text và lượt sau vẫn có thể bắt đầu.

Thử gọi handler hai lần liên tiếp trong một test điều phối: lượt thứ hai phải không gọi loadDemo trong khi busy còn true. Kiểm tra cả trường hợp loader reject để bảo đảm busy được mở trong finally. Đây là phép kiểm tra logic khác với thao tác gesture trên native view.

Với danh sách rỗng, thử trực tiếp trên cả Android và iOS. Scroll container cần chiều cao bị giới hạn từ cây cha; flex: 1 phải truyền đúng qua layout của màn hình. FlatList reference là nguồn đối chiếu cho list và refresh props, nhưng demo chưa xác nhận hành vi của mọi cấu hình lồng scroll.

Giới hạn khi nối API thật

Không dùng cùng refreshing cho mọi loại tải nếu màn hình còn initial load hoặc tải trang tiếp theo với UI khác. Xác định dữ liệu nào được thay, dữ liệu cũ có giữ khi lỗi không, và chính sách xử lý request không bao giờ kết thúc. Loader thật cần timeout/hủy theo hợp đồng riêng để finally có cơ hội được đi tới khi Promise settle.

Thông báo live region trong ví dụ dành cho Android; thử cách đọc lỗi trên iOS thay vì giả định cùng một prop bảo đảm giống nhau. Khi app có nhiều nguồn cập nhật danh sách, còn cần giải quyết thứ tự kết quả, không chỉ khóa một nút kéo.

RefreshControl chỉ cần một hợp đồng rõ ràng: bắt đầu lượt thì bật state, kết thúc lượt thì tắt, lỗi không làm mất khả năng thử lại. Giữ logic đó tách khỏi gesture giúp bạn kiểm tra và thay loader dễ hơn.

Nguồn tham khảo

  • React Native 0.88: RefreshControl
  • React Native 0.88: FlatList
  • React: useRef
  • React: useEffect

Tags: Async UIReact NativeRefreshControl
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh hoạ form TextInput validation và keyboard trong React Native

React Native TextInput: bàn phím numeric không thay thế validation

by Suong Nguyen
29/10/2026
0

Giữ input số lượng dưới dạng string trong lúc nhập, kiểm tra định dạng và khoảng giá trị khi xác nhận.

Minh hoạ state thay đổi và làm giao diện React Native cập nhật lại

React Native Switch: cập nhật value từ onValueChange và khóa đúng bằng disabled

by Suong Nguyen
28/10/2026
0

Dựng một cài đặt boolean có nguồn dữ liệu rõ ràng, tránh Switch bật rồi trở lại giá trị cũ và tách trạng thái khóa khỏi giá trị...

Minh hoạ FlatList hiển thị danh sách bài viết trong React Native

React Native SectionList: nhóm dữ liệu với key và tiêu đề riêng cho từng phần

by Suong Nguyen
27/10/2026
0

Dựng danh sách đơn theo trạng thái bằng SectionList, giữ key ổn định và xử lý nhóm rỗng cùng cập nhật dữ liệu.

Minh hoạ style và layout trong React Native với màn hình mobile, spacing và typography

React Native Image: cover và contain khác nhau trong cùng một khung ảnh

by Suong Nguyen
26/10/2026
0

Tách kích thước khung khỏi cách ảnh được co giãn, so sánh cover/contain bằng cùng ảnh nguồn và kiểm tra lỗi tải ảnh mạng.

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native RefreshControl: giữ refreshing đúng vòng đời của lượt tải
  • Phỏng vấn JavaScript: await forEach không chờ các callback async
  • Android ACTION_VIEW: mở liên kết HTTPS và xử lý khi không có app nhận

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

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

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply