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
相关产品推荐
相关产品推荐

