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

React Native FlatList未加载MySQL查询结果问题排查与优化咨询

Let's break down the issues in your code and fix them step by step, plus share some cleaner, more efficient approaches.

First, the root cause of your FlatList not rendering data

Looking at your PHP code, when there are no results, you return a plain string 'No Results Found.' instead of a consistent JSON object with an item field. When your frontend tries to access responseJson.item on a string, it gets undefined, setting dataPeople to undefined—which makes FlatList render nothing. Even when you do get valid results, there's a redundant loop in your PHP response building that could cause unexpected behavior.


Fixes for the PHP code

  1. Prevent SQL Injection: Never directly interpolate user input into SQL queries. Use prepared statements instead to keep your database safe.
  2. Consistent Response Format: Always return a JSON object with the item array, even when there are no results. This way your frontend doesn't have to handle mixed response types.
  3. Simplify Result Fetching: Use fetch_all() to get all results at once instead of looping through each row.

Here's the corrected PHP code:

<?php 
include 'koneksi-lkl.php'; 
$json = file_get_contents('php://input'); 
$obj = json_decode($json,true); 
$itemcode = $obj['itemcode'] ?? ''; // Handle case where itemcode is not provided

// Use prepared statement to avoid SQL injection
$Sql_Query = "SELECT id, itemcode, description FROM article WHERE itemcode = ? LIMIT 1";
$stmt = $con->prepare($Sql_Query);
$stmt->bind_param("s", $itemcode); // "s" denotes string type
$stmt->execute();
$result = $stmt->get_result();

// Return consistent structure: always include item array
$response = ["item" => []];
if ($result->num_rows > 0) {
  $response["item"] = $result->fetch_all(MYSQLI_ASSOC);
} 

echo json_encode($response); 
$stmt->close();
$con->close(); 
?>

Fixes for the React Native code

Even with the fixed PHP, you should add proper loading/empty state handling to give users clear feedback. Also, we'll fix edge cases where the response might not have an item field:

// Updated SearchArticle.js (class component version)
constructor(props) { 
  super(props); 
  this.state = { 
    dataPeople: [], 
    isLoading: false, 
    TextInput_ItemCode: "" 
  }; 
} 

_fetchItem = () => { 
  this.setState({ isLoading: true }); // Show loading state
  fetch("http://192.168.181.59/article/SearchArticleList.php", { 
    method: "POST", 
    headers: { 
      Accept: "application/json", 
      "Content-Type": "application/json" 
    }, 
    body: JSON.stringify({ 
      itemcode: this.state.TextInput_ItemCode, 
    }) 
  }) 
  .then((response) => response.json()) 
  .then((responseJson)=>{ 
    console.log(responseJson); 
    this.setState({ 
      isLoading: false, 
      dataPeople: responseJson.item || [] // Fallback to empty array if needed
    }); 
  }) 
  .catch((error)=>{ 
    console.error(error);
    this.setState({ 
      isLoading: false, 
      dataPeople: [] 
    });
    Alert.alert("Error", "Failed to fetch data. Please check your network.");
  }) 
}; 

// Update render to handle loading/empty states
render() { 
  const { dataPeople, isLoading } = this.state;
  return ( 
    <View style={styles.MainContainer}> 
      <Text style={{ fontSize: 20, textAlign: "center", marginBottom: 7 }}> 
        Search Article 
      </Text> 
      <TextInput 
        placeholder="Itemcode" 
        onChangeText={(TextInputValue) => this.setState({ TextInput_ItemCode: TextInputValue })} 
        underlineColorAndroid="transparent" 
        keyboardType='numeric' 
        style={styles.TextInputStyleClass} 
      /> 
      <TouchableOpacity 
        activeOpacity={0.4} 
        style={styles.TouchableOpacityStyle} 
        onPress={this._fetchItem} 
        disabled={isLoading} // Prevent duplicate requests
      > 
        <Text style={styles.TextStyle}> 
          {isLoading ? "SEARCHING..." : "SEARCH"} 
        </Text> 
      </TouchableOpacity> 

      {/* Handle loading, empty, and data states */}
      {isLoading ? (
        <ActivityIndicator size="large" color="#0000ff" style={{ marginTop: 20 }} />
      ) : dataPeople.length === 0 ? (
        <Text style={{ textAlign: "center", marginTop: 20, color: "gray" }}>
          No results found. Try a different item code.
        </Text>
      ) : (
        <FlatList 
          data={dataPeople} 
          renderItem={this._itemCoponent} 
          keyExtractor={(item) => item.id} // Use unique item ID instead of index
          ItemSeparatorComponent={this._separatorComponent} 
        />
      )}
    </View> 
  ); 
}

More Efficient & Clean Implementation (Functional Component with Hooks)

Class components work, but functional components with React Hooks are more modern and concise. Here's a polished version:

import React, { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, FlatList, ActivityIndicator, Alert, StyleSheet } from 'react-native';

const SearchArticle = () => {
  const [dataPeople, setDataPeople] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [itemCode, setItemCode] = useState("");

  const fetchItem = async () => {
    // Validate input before making request
    if (!itemCode.trim()) {
      Alert.alert("Warning", "Please enter an item code.");
      return;
    }
    setIsLoading(true);
    try {
      const response = await fetch("http://192.168.181.59/article/SearchArticleList.php", {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json"
        },
        body: JSON.stringify({ itemcode: itemCode })
      });
      const responseJson = await response.json();
      setDataPeople(responseJson.item || []);
    } catch (error) {
      console.error(error);
      Alert.alert("Error", "Failed to fetch data. Please check your network.");
      setDataPeople([]);
    } finally {
      setIsLoading(false);
    }
  };

  const renderItem = ({ item }) => (
    <View style={styles.itemContainer}>
      <View style={styles.itemContent}>
        <Text style={styles.itemCodeText}>{item.id} - {item.itemcode}</Text>
        <Text style={styles.itemDescText}>{item.description}</Text>
      </View>
    </View>
  );

  const renderSeparator = () => (
    <View style={styles.separator} />
  );

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Search Article</Text>
      <TextInput
        placeholder="Itemcode"
        value={itemCode}
        onChangeText={setItemCode}
        keyboardType="numeric"
        style={styles.input}
      />
      <TouchableOpacity
        style={styles.searchButton}
        onPress={fetchItem}
        disabled={isLoading}
      >
        <Text style={styles.buttonText}>{isLoading ? "SEARCHING..." : "SEARCH"}</Text>
      </TouchableOpacity>

      {isLoading ? (
        <ActivityIndicator size="large" color="#2196F3" style={styles.loader} />
      ) : dataPeople.length === 0 ? (
        <Text style={styles.emptyText}>No results found. Try another item code.</Text>
      ) : (
        <FlatList
          data={dataPeople}
          renderItem={renderItem}
          keyExtractor={(item) => item.id}
          ItemSeparatorComponent={renderSeparator}
          style={styles.list}
        />
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: "#fff"
  },
  title: {
    fontSize: 20,
    textAlign: "center",
    marginBottom: 16
  },
  input: {
    height: 40,
    borderColor: "#ccc",
    borderWidth: 1,
    borderRadius: 4,
    paddingHorizontal: 8,
    marginBottom: 16
  },
  searchButton: {
    backgroundColor: "#2196F3",
    padding: 12,
    borderRadius: 4,
    alignItems: "center"
  },
  buttonText: {
    color: "#fff",
    fontSize: 16
  },
  loader: {
    marginTop: 24
  },
  emptyText: {
    textAlign: "center",
    marginTop: 24,
    color: "#666",
    fontSize: 16
  },
  list: {
    marginTop: 16
  },
  itemContainer: {
    flex: 1,
    marginLeft: 8
  },
  itemContent: {
    flex: 2,
    paddingVertical: 8
  },
  itemCodeText: {
    fontSize: 14,
    fontWeight: "500"
  },
  itemDescText: {
    fontSize: 12,
    color: "#666",
    marginTop: 4
  },
  separator: {
    height: 0.5,
    backgroundColor: "#ccc",
    marginVertical: 8
  }
});

export default SearchArticle;

Key Improvements

  • SQL Injection Protection: Prepared statements in PHP eliminate a critical security risk.
  • Consistent API Responses: Your frontend always gets a predictable JSON structure, avoiding runtime errors.
  • User Feedback: Loading states, empty state messages, and input validation keep users informed.
  • Modern React Syntax: Functional components with Hooks are easier to read, test, and maintain.
  • Error Handling: Clear alerts for network errors help users troubleshoot issues.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:17:58