React Native中DropDownPicker的onChangeValue事件无法触发求助
React Native DropDownPicker onChange事件不触发的修复方案
我在React Native中使用DropDownPicker组件时,onChangeValue事件无法触发。尝试过onChange和onChangeItem方法,参考官方文档后仍未解决,相关代码如下:
import React, { useEffect, useState } from 'react'; import {View, Text, Button, TextInput, FlatList, ActivityIndicator, StyleSheet, Image} from 'react-native'; import filter from 'lodash.filter'; import DropDownPicker from 'react-native-dropdown-picker'; const CarList = () => { const [isLoading, setIsLoading] = useState(false); const [data, setData] = useState([]); const [error, setError] = useState(null); const [query, setQuery] = useState(''); const [fullData, setFullData] = useState([]); const [selected, setSelected] = useState(""); const [open, setOpen] = useState(false); const [childOpen, setChildOpen] = useState(false); const [filterOption, setfilteroption] = useState([ {label: 'Color', value: 'Color'}, {label: 'Model', value: 'Model'}, {label: 'Year', value: 'Year'} ]); const [value, setValue] = useState(null); const [childvalue, setChildValue] = useState([]); useEffect(() => { setIsLoading(true); fetch(`https://myfakeapi.com/api/cars/?seed=1&page=1&results=20`) .then(response => response.json()) .then(response => { setData(response.cars); setFullData(response.cars); setIsLoading(false); }) .catch(err => { setIsLoading(false); setError(err); }); }, []); if (isLoading) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <ActivityIndicator size="large" color="#5500dc" /> </View> ); } if (error) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text style={{ fontSize: 18}}> Error fetching data... Check your network connection! </Text> </View> ); } const handleSearch = text => { const formattedQuery = text.toLowerCase(); const filteredData = filter(fullData, user => { return contains(user, formattedQuery); }); setData(filteredData); setQuery(text); }; const contains = ({ car, car_model,car_color }, query) => { if (car.toLowerCase().includes(query) || car_model.toLowerCase().includes(query) || car_color.toLowerCase().includes(query)) { return true; } return false; }; const color = [...new Set(data.map((item) => item.car_color))]; const model = [...new Set(data.map((item) => item.car_model))]; const year = [...new Set(data.map((item) => item.car_model_year))]; //this is not triggering const changeSelectOptionHandler = (value) => { console.log("hi") setSelected(value); }; if (selected === "Color") { setChildValue(color) } else if (selected === "Model") { setChildValue(model) } else if (selected === "Year") { setChildValue(year) } function renderHeader() { return ( <View style={{ backgroundColor: '#fff', padding: 10, marginVertical: 10, borderRadius: 20 }} > <TextInput autoCapitalize="none" autoCorrect={false} clearButtonMode="always" value={query} onChangeText={queryText => handleSearch(queryText)} placeholder="Search" style={{ backgroundColor: '#fff', paddingHorizontal: 20 }} /> <DropDownPicker onChangeItem={changeSelectOptionHandler} open={open} value={value} items={filterOption} setOpen={setOpen} setValue={setValue} setItems={setfilteroption} dropDownDirection="TOP" style={{ padding: 5, margin: 5, width: 200, flexDirection: 'row' // borderRadius: 20 }} /> <DropDownPicker open={childOpen} items={childvalue} setOpen={setChildOpen} setItems={setChildValue} dropDownDirection="TOP" /> </View> ); } return ( <View style={styles.container}> <Text style={styles.text}>Favorite Contacts</Text> <FlatList keyboardShouldPersistTaps="always" ListHeaderComponent={renderHeader} data={data} keyExtractor={({ id }) => id} renderItem={({ item }) => ( <View style={styles.listItem}> <Image source={{ uri: 'https://picsum.photos/200', }} style={styles.coverImage} /> <View style={styles.metaInfo}> <Text style={styles.title}>{`${item.car} ${item.car_model}`}</Text> <Text>Color: {`${item.car_color}`}</Text> <Text>Price: {`${item.price}`}</Text> </View> </View> )} /> </View> ); }
问题分析
导致事件不触发和功能异常的核心原因:
- onChangeItem回调参数处理错误:该回调接收的是选中的
item对象,而非直接的value值,原代码直接拿参数赋值,逻辑错误。 - 无限重渲染阻塞事件:组件函数体中直接写
if(selected === ...)并调用setChildValue,会导致每次渲染都触发状态更新,陷入无限重渲染循环,干扰组件事件响应。 - 子Dropdown数据格式错误:
childvalue是纯字符串数组,但DropDownPicker要求items是包含label和value的对象数组。 - 冗余属性干扰组件状态:第一个Dropdown设置了
setItems={setfilteroption},但filterOption是固定选项,不需要动态修改,该属性会干扰组件内部状态管理。
修复方案
import React, { useEffect, useState } from 'react'; import { View, Text, TextInput, FlatList, ActivityIndicator, StyleSheet, Image } from 'react-native'; import filter from 'lodash.filter'; import DropDownPicker from 'react-native-dropdown-picker'; const CarList = () => { const [isLoading, setIsLoading] = useState(false); const [data, setData] = useState([]); const [error, setError] = useState(null); const [query, setQuery] = useState(''); const [fullData, setFullData] = useState([]); const [selected, setSelected] = useState(""); const [open, setOpen] = useState(false); const [childOpen, setChildOpen] = useState(false); const [filterOption] = useState([ { label: 'Color', value: 'Color' }, { label: 'Model', value: 'Model' }, { label: 'Year', value: 'Year' } ]); const [value, setValue] = useState(null); const [childValue, setChildValue] = useState(null); const [childItems, setChildItems] = useState([]); useEffect(() => { setIsLoading(true); fetch(`https://myfakeapi.com/api/cars/?seed=1&page=1&results=20`) .then(response => response.json()) .then(response => { setData(response.cars); setFullData(response.cars); setIsLoading(false); }) .catch(err => { setIsLoading(false); setError(err); }); }, []); // 监听selected和data变化,动态更新子Dropdown选项 useEffect(() => { let newItems = []; if (selected === "Color") { newItems = [...new Set(data.map(item => item.car_color))].map(val => ({ label: val, value: val })); } else if (selected === "Model") { newItems = [...new Set(data.map(item => item.car_model))].map(val => ({ label: val, value: val })); } else if (selected === "Year") { newItems = [...new Set(data.map(item => item.car_model_year))].map(val => ({ label: val.toString(), value: val })); } setChildItems(newItems); // 切换分类后重置子Dropdown选中值 setChildValue(null); }, [selected, data]); if (isLoading) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <ActivityIndicator size="large" color="#5500dc" /> </View> ); } if (error) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text style={{ fontSize: 18 }}> Error fetching data... Check your network connection! </Text> </View> ); } const handleSearch = text => { const formattedQuery = text.toLowerCase(); const filteredData = filter(fullData, user => { return contains(user, formattedQuery); }); setData(filteredData); setQuery(text); }; const contains = ({ car, car_model, car_color }, query) => { if (car.toLowerCase().includes(query) || car_model.toLowerCase().includes(query) || car_color.toLowerCase().includes(query)) { return true; } return false; }; // 修正onChangeItem回调,正确获取选中项的value const changeSelectOptionHandler = (item) => { console.log("选中的分类:", item.value); setSelected(item.value); }; function renderHeader() { return ( <View style={{ backgroundColor: '#fff', padding: 10, marginVertical: 10, borderRadius: 20 }} > <TextInput autoCapitalize="none" autoCorrect={false} clearButtonMode="always" value={query} onChangeText={queryText => handleSearch(queryText)} placeholder="Search" style={{ backgroundColor: '#fff', paddingHorizontal: 20, marginBottom: 10 }} /> <DropDownPicker onChangeItem={changeSelectOptionHandler} open={open} value={value} items={filterOption} setOpen={setOpen} setValue={setValue} dropDownDirection="TOP" style={{ padding: 5, margin: 5, width: 200, }} /> {selected && ( <DropDownPicker open={childOpen} value={childValue} items={childItems} setOpen={setChildOpen} setValue={setChildValue} dropDownDirection="TOP" style={{ padding: 5, margin: 5, width: 200, }} /> )} </View> ); } return ( <View style={styles.container}> <Text style={styles.text}>Favorite Contacts</Text> <FlatList keyboardShouldPersistTaps="always" ListHeaderComponent={renderHeader} data={data} keyExtractor={({ id }) => id.toString()} renderItem={({ item }) => ( <View style={styles.listItem}> <Image source={{ uri: 'https://picsum.photos/200', }} style={styles.coverImage} /> <View style={styles.metaInfo}> <Text style={styles.title}>{`${item.car} ${item.car_model}`}</Text> <Text>Color: {`${item.car_color}`}</Text> <Text>Price: {`${item.price}`}</Text> </View> </View> )} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 10, backgroundColor: '#f5f5f5' }, text: { fontSize: 20, fontWeight: 'bold', marginBottom: 10 }, listItem: { flexDirection: 'row', backgroundColor: '#fff', borderRadius: 10, padding: 10, marginBottom: 10, alignItems: 'center' }, coverImage: { width: 60, height: 60, borderRadius: 30 }, metaInfo: { marginLeft: 10 }, title: { fontSize: 16, fontWeight: 'bold' } }); export default CarList;
内容的提问来源于stack exchange,提问作者Anamika Singh
相关产品推荐
相关产品推荐

