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

Expo React搜索栏无响应:如何关联API实现股票代码搜索?

问题解决:股票搜索功能实现

你的问题核心是搜索栏没有和数据逻辑关联——既没有把输入的关键词传递到父组件,也没有根据关键词触发数据查询/过滤。需要从组件通信和数据处理两方面修改,下面是具体方案:

1. 实现搜索栏与父组件的状态同步

首先要让SearchBar组件能把用户输入的关键词传递给父组件Stocks,同时父组件维护搜索关键词的状态:

  • 在父组件添加搜索关键词状态:
    const [searchQuery, setSearchQuery] = useState('');
    
  • 修改SearchBar组件,添加内部输入状态,并通过回调把值传给父组件:
    function SearchBar({ onSearchChange }) {
      const [inputValue, setInputValue] = useState('');
      
      const handleInputChange = (text) => {
        setInputValue(text);
        onSearchChange(text);
      };
      
      return (
        <VStack my="4" space={5} w="100%" maxW="300px" divider={<Box px="2"><Divider /></Box>}>
          <VStack w="100%" space={5} alignSelf="center">
            <Heading fontSize="lg">Search for stocks</Heading>
            <Input
              placeholder="Search"
              variant="filled"
              width="100%"
              borderRadius="10"
              py="1"
              px="2"
              value={inputValue}
              onChangeText={handleInputChange}
              InputLeftElement={<Icon ml="2" size="4" color="gray.400" as={<Ionicons name="ios-search" />} />}
            />
          </VStack>
        </VStack>
      );
    }
    
  • 在父组件调用SearchBar时传入回调:
    <SearchBar onSearchChange={setSearchQuery} />
    

2. 根据搜索关键词处理数据

有两种实现方式,根据你的后端接口情况选择:

方式一:前端过滤现有数据(适合数据量不大的情况)

如果后端没有提供搜索接口,直接在前端过滤已获取的股票数据:

// 父组件中,根据searchQuery过滤数据
const filteredData = searchQuery 
  ? data.filter(item => item.symbol.toLowerCase().includes(searchQuery.toLowerCase()))
  : data;

// 渲染FlatList时使用filteredData
<FlatList
  data={filteredData}
  renderItem={renderItem}
/>

方式二:调用后端搜索接口(推荐,适合数据量大的情况)

如果后端提供了带搜索参数的接口(比如http://localhost:8080/search?symbol=XXX),修改fetchData函数支持传入搜索关键词:

const fetchData = async (query = '') => {
  setLoading(true);
  const url = query 
    ? `http://localhost:8080/search?symbol=${encodeURIComponent(query)}`
    : 'http://localhost:8080/all';
  
  const resp = await fetch(url);
  const data = await resp.json();
  setData(data);
  setLoading(false);
};

// 监听searchQuery变化,触发搜索(添加防抖避免频繁请求)
useEffect(() => {
  const timer = setTimeout(() => {
    fetchData(searchQuery);
  }, 300);
  
  return () => clearTimeout(timer);
}, [searchQuery]);

完整修改后的代码

import React, { useState, useEffect } from "react";
import { VStack, Input, Icon, Divider, Heading, Box, FlatList, Center, NativeBaseProvider, Text } from "native-base";
import { Ionicons } from "@expo/vector-icons";

export default function Stocks() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [searchQuery, setSearchQuery] = useState('');

  // 支持带搜索参数的fetch函数
  const fetchData = async (query = '') => {
    setLoading(true);
    const url = query 
      ? `http://localhost:8080/search?symbol=${encodeURIComponent(query)}`
      : 'http://localhost:8080/all';
    
    try {
      const resp = await fetch(url);
      const data = await resp.json();
      setData(data);
    } catch (err) {
      console.error('请求失败:', err);
    } finally {
      setLoading(false);
    }
  };

  // 组件挂载时获取全部数据
  useEffect(() => {
    fetchData();
  }, []);

  // 监听搜索关键词变化,触发搜索(带防抖)
  useEffect(() => {
    const timer = setTimeout(() => {
      fetchData(searchQuery);
    }, 300);
    
    return () => clearTimeout(timer);
  }, [searchQuery]);

  const renderItem = ({ item }) => {
    return (
      <Box px={16} py={2} rounded="md" bg="primary.900" my={0.5}>
        <Text>{item.symbol}</Text>
        <Text fontSize="sm" color="gray.300">{item.name}</Text>
      </Box>
    );
  };

  return (
    <NativeBaseProvider>
      <Center flex={1}>
        <Box> Fetch API</Box>
        <SearchBar onSearchChange={setSearchQuery} />
        {loading && <Box>Loading..</Box>}
        {!loading && (
          <FlatList
            data={data}
            renderItem={renderItem}
            keyExtractor={(item) => item.symbol}
          />
        )}
      </Center>
    </NativeBaseProvider>
  );
}

function SearchBar({ onSearchChange }) {
  const [inputValue, setInputValue] = useState('');
  
  const handleInputChange = (text) => {
    setInputValue(text);
    onSearchChange(text);
  };
  
  return (
    <VStack my="4" space={5} w="100%" maxW="300px" divider={<Box px="2"><Divider /></Box>}>
      <VStack w="100%" space={5} alignSelf="center">
        <Heading fontSize="lg">Search for stocks</Heading>
        <Input
          placeholder="Search"
          variant="filled"
          width="100%"
          borderRadius="10"
          py="1"
          px="2"
          value={inputValue}
          onChangeText={handleInputChange}
          InputLeftElement={<Icon ml="2" size="4" color="gray.400" as={<Ionicons name="ios-search" />} />}
        />
      </VStack>
    </VStack>
  );
}

额外优化点

  • 给FlatList添加keyExtractor,避免渲染警告
  • 给fetch添加错误捕获,避免请求失败导致页面卡住
  • 搜索时添加防抖,减少不必要的接口请求
  • 优化renderItem的布局,用Text组件包裹内容,样式更可控

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:25:39