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

如何在React Native中基于API数据展示自定义配送进度条?已尝试step-indicators模块但不符合需求

Hey there! I get it—off-the-shelf modules like step-indicators don’t always fit the exact design you need, especially for delivery progress tracking tied to real API data. Let’s build a custom, flexible progress bar that you can tailor to your UI and data structure.

Core Approach
  • First, fetch delivery step data from your API (each step should include a name, status like completed/active/pending, and unique ID)
  • Use React Native's basic View components to build step nodes and connecting lines, dynamically updating styles based on each step's status
  • Map directly to your API data structure so the progress bar automatically updates when your backend data changes
Full Implementation Code

First, let's assume your API returns data in this structure:

// Sample API response data
const deliveryStepsFromAPI = [
  { id: 1, title: "Order Confirmed", status: "completed" },
  { id: 2, title: "Shipped from Warehouse", status: "completed" },
  { id: 3, title: "Out for Delivery", status: "active" },
  { id: 4, title: "Delivered", status: "pending" }
];

Now build the custom progress bar component:

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

const DeliveryProgressBar = ({ steps }) => {
  // Get dynamic styles for step nodes based on status
  const getNodeStyle = (status) => {
    switch(status) {
      case 'completed':
        return {
          backgroundColor: '#27ae60',
          borderColor: '#27ae60'
        };
      case 'active':
        return {
          backgroundColor: '#3498db',
          borderColor: '#3498db'
        };
      default:
        return {
          backgroundColor: '#e0e0e0',
          borderColor: '#bdbdbd'
        };
    }
  };

  // Get dynamic styles for connecting lines
  const getLineStyle = (index) => {
    if (index === 0) return {}; // No line before the first step
    const previousStep = steps[index - 1];
    if (previousStep.status === 'completed' || previousStep.status === 'active') {
      return { backgroundColor: '#27ae60' };
    }
    return { backgroundColor: '#bdbdbd' };
  };

  return (
    <View style={styles.progressContainer}>
      {steps.map((step, index) => (
        <View key={step.id} style={styles.stepWrapper}>
          {/* Connecting line (hidden for first step) */}
          {index !== 0 && (
            <View style={[styles.connectingLine, getLineStyle(index)]} />
          )}
          {/* Step node */}
          <View style={[styles.stepNode, getNodeStyle(step.status)]}>
            {step.status === 'completed' && <Text style={styles.nodeIcon}>✓</Text>}
            {step.status === 'active' && <Text style={styles.nodeIcon}>•</Text>}
            {step.status === 'pending' && <Text style={styles.nodeIcon}>{index + 1}</Text>}
          </View>
          {/* Step title */}
          <Text style={[styles.stepTitle, step.status !== 'pending' && styles.activeTitle]}>
            {step.title}
          </Text>
        </View>
      ))}
    </View>
  );
};

const styles = StyleSheet.create({
  progressContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingVertical: 20,
    paddingHorizontal: 12,
    backgroundColor: '#ffffff',
    borderRadius: 10,
    marginHorizontal: 16,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4
  },
  stepWrapper: {
    flex: 1,
    alignItems: 'center',
    position: 'relative'
  },
  connectingLine: {
    position: 'absolute',
    left: -50,
    top: 12,
    width: 100,
    height: 2
  },
  stepNode: {
    width: 26,
    height: 26,
    borderRadius: 13,
    borderWidth: 2,
    justifyContent: 'center',
    alignItems: 'center',
    marginBottom: 6
  },
  nodeIcon: {
    color: '#ffffff',
    fontSize: 12,
    fontWeight: '600'
  },
  stepTitle: {
    fontSize: 11,
    color: '#757575',
    textAlign: 'center'
  },
  activeTitle: {
    color: '#27ae60',
    fontWeight: '500'
  }
});

export default DeliveryProgressBar;
How to Use the Component

In your screen, fetch the API data and pass it to the progress bar:

import React, { useEffect, useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import DeliveryProgressBar from './DeliveryProgressBar';

const DeliveryTrackingScreen = () => {
  const [deliverySteps, setDeliverySteps] = useState([]);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    // Replace with your actual API call
    const fetchDeliveryData = async () => {
      try {
        const response = await fetch('https://your-api-endpoint.com/delivery-steps');
        const data = await response.json();
        setDeliverySteps(data);
      } catch (error) {
        console.error('Failed to fetch delivery data:', error);
      } finally {
        setIsLoading(false);
      }
    };

    fetchDeliveryData();
  }, []);

  return (
    <View style={styles.screenContainer}>
      {isLoading ? (
        <Text style={styles.loadingText}>Loading delivery progress...</Text>
      ) : (
        <DeliveryProgressBar steps={deliverySteps} />
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  screenContainer: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#f5f5f5'
  },
  loadingText: {
    textAlign: 'center',
    fontSize: 14,
    color: '#616161'
  }
});

export default DeliveryTrackingScreen;
Customization Tips
  • Style Tweaks: Adjust colors, node sizes, border widths, or shadows in the styles object to match your design exactly
  • Extra Statuses: Add more cases to getNodeStyle and getLineStyle if your API returns additional statuses (like delayed or failed)
  • Animations: Use React Native's Animated module to add smooth transitions when statuses change (e.g., fade in completed nodes)
  • Scrollable Layout: If you have more than 4 steps, add overflow: 'scroll' to the progressContainer style to make it horizontally scrollable

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 10:34:08