React Native中Ref数组更新后Dropdown组件未重新渲染问题
问题:React Native动态下拉框数据不更新
我实现了一个基于文本输入的动态下拉框,用于展示匹配度最高的字符串。使用useRef存储文本输入值以及API返回的数组,控制台中能看到数组值每次都会变化,但将ref数组传递给Dropdown组件的props后,组件内部的值却没有更新。希望每次按键输入时,新值都能传递到下拉框中。
核心原因
useRef的变更不会触发组件重渲染。你用arrRef存储下拉数据,更新ref.current后,StartScreen组件不会重新渲染,Dropdown自然无法获取到最新数据。
修复方案
- 用
useState替代useRef存储下拉数据:状态变更会触发组件重渲染,确保Dropdown能获取到最新数据 - 简化数据处理逻辑:直接将API返回的数组赋值给状态,无需额外的
addToArr函数 - 调整Dropdown组件的props类型:接收普通数组而非Ref对象,简化组件内部逻辑
修改后的StartScreen代码
import React, { useState, useRef } from 'react'; import styled ,{css} from 'styled-components/native'; import { Container, screenWidth } from '../utils/shared'; import { StackNavigationProp } from '@react-navigation/stack'; import { StackParamList } from '../navigation/StackNavigation'; import { useNavigation } from '@react-navigation/native'; import { getCityByName } from '../utils/cityApi'; import mapPng from "../assets/map.png"; //Components import BackArrowButton from '../components/Buttons/BackArrowButton'; import Search from '../components/Inputs/Search'; import RegularText from '../components/Text/RegularText'; import TextButton from '../components/Buttons/TextButton'; import RegularButton from '../components/Buttons/RegularButton'; import Dropdown from '../components/Sliders/Dropdown'; const StartScreen: React.FC = () => { // 输入值用useRef存储(无需触发重渲染,合理) const nameRef = useRef<string>(""); const updateNameRef = (name: string)=>{ nameRef.current = name; fetchCities(); }; // 改用useState存储下拉数据,状态变更触发重渲染 const [dropdownArr, setDropdownArr] = useState<string[]>([]); type stackProps = StackNavigationProp<StackParamList ,"Start">; const navigation = useNavigation<stackProps>(); const goBack = () =>{ navigation.navigate("Welcome"); }; const skipPress = () =>{ navigation.navigate("Home") }; const StyledImage = styled.Image` width: 60%; height: 200px; object-fit:cover; `; const StyledView = styled.View` justify-content:space-between; align-items: center; height: 400px; display: flex; width: ${screenWidth}px; `; const customSpace = css` margin-top: 21px; `; // 简化API数据处理逻辑 const fetchCities = async () => { if (nameRef.current !== "") { const arr = await getCityByName(nameRef.current, 0, 5); setDropdownArr(arr || []); } else { setDropdownArr([]); } }; return ( <Container> <BackArrowButton onPress={goBack}/> <StyledView> <StyledImage source={mapPng} /> <RegularText str='Please enter your location' customCss={customSpace}/> <Search placeHolder='City...' updateNameRef={updateNameRef}/> {/* 直接传递普通数组给Dropdown */} <Dropdown arr={dropdownArr}/> <RegularButton ButtonText='Enter' onPress={skipPress} customCss={customSpace}/> <TextButton str='skip' onPress={skipPress} size={17} customCss={customSpace}/> </StyledView> </Container> ); } export default StartScreen;
修改后的Dropdown组件代码
import React from 'react'; import styled from 'styled-components/native'; import { colorPalette } from '../../utils/colors'; import { screenWidth } from '../../utils/shared'; //Components import NameCard from '../Cards/NameCard'; import { FlatList } from 'react-native'; // 调整props类型为普通字符串数组 interface DropdownProps { arr: string[]; } const StyledView = styled.View` max-height: 90px; min-height: 0px; width: ${screenWidth*0.7}px; background: ${colorPalette.white}; border-radius: 0px 0px 7px 7px; position: relative; padding-top: 7px; `; const BorderInside = styled.View` position: absolute; top: 1px; left: 2.5%; width: 95%; height: calc(100% - 0.5px); border: 0.2px solid grey; `; const Dropdown: React.FC<DropdownProps> = (props) => { return ( <StyledView> <BorderInside /> <FlatList data={props.arr} keyExtractor={(item) => item} renderItem={({ item }) => ( <NameCard key={item} str={item} /> )} /> </StyledView> ); } export default Dropdown;
内容的提问来源于stack exchange,提问作者Benjamin Hanonove
相关产品推荐
相关产品推荐

