You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native:API响应SQLite存储及离线交易状态同步实现问询

Got it, let's walk through building this React Native app with offline support step by step. I'll cover every part from setting up local storage to handling syncing when the network comes back.

1. First, Set Up Dependencies

You'll need a few key libraries to make this work:

  • expo-sqlite (or react-native-sqlite-storage if you're not using Expo) for local SQLite storage
  • @react-native-community/netinfo to detect network connectivity
  • axios (or native fetch) for API calls

Install them with:

# If using Expo
npx expo install expo-sqlite @react-native-community/netinfo axios

# For bare React Native
npm install react-native-sqlite-storage @react-native-community/netinfo axios
2. Design Your SQLite Database

First, create a table to store transaction data. We'll add an isSynced flag to track if local changes have been sent to the server:

// db.js
import * as SQLite from 'expo-sqlite';

const db = SQLite.openDatabase('transactions.db');

export const initDatabase = () => {
  return new Promise((resolve, reject) => {
    db.transaction(tx => {
      tx.executeSql(
        `CREATE TABLE IF NOT EXISTS transactions (
          id INTEGER PRIMARY KEY NOT NULL,
          amount TEXT NOT NULL,
          date TEXT NOT NULL,
          status TEXT NOT NULL,
          isSynced INTEGER DEFAULT 1
        );`,
        [],
        () => resolve(),
        (_, error) => reject(error)
      );
    });
  });
};

The isSynced field uses 1 for synced (default) and 0 for pending changes that need to be sent to the server.

3. Initial Data Sync (First Load)

On app launch, check if there's a network connection. If yes, pull data from the server and save it locally. If not, load directly from the database:

// TransactionService.js
import axios from 'axios';
import { db } from './db';
import NetInfo from '@react-native-community/netinfo';

export const loadTransactions = async () => {
  const networkState = await NetInfo.fetch();
  
  if (networkState.isConnected) {
    // Fetch from server
    const response = await axios.get('https://your-api.com/transactions');
    const serverTransactions = response.data;
    
    // Save to local DB (replace existing to keep data up to date)
    await saveTransactionsToDB(serverTransactions);
  }
  
  // Load from local DB regardless of network
  return getTransactionsFromDB();
};

const saveTransactionsToDB = (transactions) => {
  return new Promise((resolve, reject) => {
    db.transaction(tx => {
      transactions.forEach(transaction => {
        tx.executeSql(
          `INSERT OR REPLACE INTO transactions 
           (id, amount, date, status) 
           VALUES (?, ?, ?, ?)`,
          [transaction.id, transaction.amount, transaction.date, transaction.status],
          null,
          (_, error) => console.error('Error saving transaction:', error)
        );
      });
    }, reject, resolve);
  });
};

const getTransactionsFromDB = () => {
  return new Promise((resolve, reject) => {
    db.transaction(tx => {
      tx.executeSql(
        'SELECT * FROM transactions ORDER BY date DESC',
        [],
        (_, { rows }) => resolve(rows._array),
        (_, error) => reject(error)
      );
    });
  });
};
4. Offline Transaction Status Updates

When a user modifies a transaction status, first update the local database and mark it as unsynced. This ensures the change is visible immediately even without network:

// TransactionService.js
export const updateTransactionStatus = async (transactionId, newStatus) => {
  return new Promise((resolve, reject) => {
    db.transaction(tx => {
      tx.executeSql(
        `UPDATE transactions 
         SET status = ?, isSynced = 0 
         WHERE id = ?`,
        [newStatus, transactionId],
        (_, result) => resolve(result),
        (_, error) => reject(error)
      );
    });
  });
};

In your component, call this function when the user selects a new status, then refresh the local list:

// TransactionList.js
import { useState, useEffect } from 'react';
import { View, Text, Button, FlatList, StyleSheet } from 'react-native';
import { loadTransactions, updateTransactionStatus } from './TransactionService';

const TransactionList = () => {
  const [transactions, setTransactions] = useState([]);

  useEffect(() => {
    loadTransactions().then(setTransactions);
  }, []);

  const handleStatusChange = async (id, newStatus) => {
    await updateTransactionStatus(id, newStatus);
    // Refresh the list after local update
    const updatedTransactions = await loadTransactions();
    setTransactions(updatedTransactions);
  };

  return (
    <FlatList
      data={transactions}
      keyExtractor={item => item.id.toString()}
      renderItem={({ item }) => (
        <View style={styles.transactionItem}>
          <Text style={styles.amountText}>Amount: ${item.amount}</Text>
          <Text style={styles.statusText}>Status: {item.status}</Text>
          <View style={styles.buttonGroup}>
            <Button 
              title="Mark Completed" 
              onPress={() => handleStatusChange(item.id, 'completed')} 
              color="#4CAF50"
            />
            <Button 
              title="Mark Pending" 
              onPress={() => handleStatusChange(item.id, 'pending')} 
              color="#FFC107"
            />
          </View>
        </View>
      )}
    />
  );
};

const styles = StyleSheet.create({
  transactionItem: {
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#eee'
  },
  amountText: {
    fontSize: 16,
    marginBottom: 8
  },
  statusText: {
    fontSize: 14,
    color: '#666',
    marginBottom: 12
  },
  buttonGroup: {
    flexDirection: 'row',
    gap: 10
  }
});

export default TransactionList;
5. Sync Pending Changes When Network Returns

Set up a network listener to detect when connectivity is restored, then sync all unsynced changes to the server:

// SyncService.js
import NetInfo from '@react-native-community/netinfo';
import axios from 'axios';
import { db } from './db';

export const setupSyncListener = () => {
  NetInfo.addEventListener(state => {
    if (state.isConnected) {
      syncPendingTransactions();
    }
  });
};

const syncPendingTransactions = async () => {
  // Get all unsynced transactions
  const pendingTransactions = await getPendingTransactions();
  
  for (const transaction of pendingTransactions) {
    try {
      // Send update to server
      await axios.put(`https://your-api.com/transactions/${transaction.id}`, {
        status: transaction.status
      });
      
      // Mark as synced in local DB
      await markTransactionAsSynced(transaction.id);
    } catch (error) {
      console.error('Failed to sync transaction:', transaction.id, error);
      // Leave it as unsynced to try again next time network is back
    }
  }
};

const getPendingTransactions = () => {
  return new Promise((resolve, reject) => {
    db.transaction(tx => {
      tx.executeSql(
        'SELECT * FROM transactions WHERE isSynced = 0',
        [],
        (_, { rows }) => resolve(rows._array),
        (_, error) => reject(error)
      );
    });
  });
};

const markTransactionAsSynced = (transactionId) => {
  return new Promise((resolve, reject) => {
    db.transaction(tx => {
      tx.executeSql(
        'UPDATE transactions SET isSynced = 1 WHERE id = ?',
        [transactionId],
        (_, result) => resolve(result),
        (_, error) => reject(error)
      );
    });
  });
};

Initialize the sync listener when your app starts (e.g., in App.js):

// App.js
import { useEffect } from 'react';
import { initDatabase } from './db';
import { setupSyncListener } from './SyncService';
import TransactionList from './TransactionList';

export default function App() {
  useEffect(() => {
    const initApp = async () => {
      await initDatabase();
      setupSyncListener();
    };
    initApp();
  }, []);

  return <TransactionList />;
}
6. Key Notes for Reliability
  • Error Handling: Add more robust error handling for API calls and database operations (e.g., exponential backoff for failed syncs).
  • Conflict Resolution: If the server updates a transaction while the user is offline, add a version field to track which data is newer (server version takes priority, or prompt the user to resolve conflicts).
  • Loading States: Add loading spinners when fetching data or syncing changes to keep users informed.

内容的提问来源于stack exchange,提问作者DCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:24:04