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

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>
      
    );

 
}

问题分析

导致事件不触发和功能异常的核心原因:

  1. onChangeItem回调参数处理错误:该回调接收的是选中的item对象,而非直接的value值,原代码直接拿参数赋值,逻辑错误。
  2. 无限重渲染阻塞事件:组件函数体中直接写if(selected === ...)并调用setChildValue,会导致每次渲染都触发状态更新,陷入无限重渲染循环,干扰组件事件响应。
  3. 子Dropdown数据格式错误:childvalue是纯字符串数组,但DropDownPicker要求items是包含label和value的对象数组。
  4. 冗余属性干扰组件状态:第一个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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:20:19