hossein-zare / react-native-dropdown-picker

A single / multiple, categorizable, customizable, localizable and searchable item picker (drop-down) component for react native which supports both Android & iOS.
https://hossein-zare.github.io/react-native-dropdown-picker-website/
MIT License
970 stars 294 forks source link

DropDown Picker throws key error when opened #634

Closed 123epsilon closed 1 year ago

123epsilon commented 1 year ago

I get the following warning when opening the drop down picker - it does not affect anything functionally but I am wondering whether this is expected behavior?:

Warning: Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future 
version.%s, [object Object],

Here is a snippet of my component:

function CreateShiftComponent(props) {
  const activeShiftInfos = props.shiftInfos;

  const [selectedShiftInfo, setSelectedShiftInfo] = useState(null);
  const [openInfoPicker, setOpenInfoPicker] = useState(false);
  const [hourlyBonus, setHourlyBonus] = useState(0.0);
  const [flatBonus, setFlatBonus] = useState(0.0);
  const [shiftNotes, setShiftNotes] = useState("");
  const [numShiftersNeeded, setNumShiftersNeeded] = useState(1);

  const [startTime, setStartTime] = useState(
    new Date().toISOString().slice(0, 19)
  );
  const [showStartPicker, setShowStartPicker] = useState(false);
  const [endTime, setEndTime] = useState(new Date().toISOString().slice(0, 19));
  const [showEndPicker, setShowEndPicker] = useState(false);

  const [doSubmit, setDoSubmit] = useState(false);
  const [error, setError] = useState(null);

  const { state, dispatch } = useContext(AppContext);

  let info_list = [];
  activeShiftInfos.forEach((item) => {
    info_list.push({ label: item.title, value: item });
  });

 ...

  return (
    <SafeAreaView>
      {error && <Text style={{ color: "red" }}>{error}</Text>}

      <Text>Select Shift Type</Text>
      <DropDownPicker
        containerProps={{
          height: openInfoPicker === true ? info_list.length * 75 : null,
          backgroundColor: "#fff",
        }}
        open={openInfoPicker}
        value={selectedShiftInfo}
        items={info_list}
        setOpen={setOpenInfoPicker}
        setValue={setSelectedShiftInfo}
      />

      <Text>Number of Shifters Required: </Text>
      <TextInput
        keyboardType="numeric"
        value={numShiftersNeeded}
        onChangeText={setNumShiftersNeeded}
      />

      <TouchableHighlight onPress={() => setShowStartPicker(true)}>
        <Text>Start Time: {startTime}</Text>
      </TouchableHighlight>
      <DateTimePickerModal
        isVisible={showStartPicker}
        mode="datetime"
        onConfirm={(date) => {
          setStartTime(date.toISOString().slice(0, 19));
          setShowStartPicker(false);
        }}
        onCancel={() => setShowStartPicker(false)}
      />

      ...

      <Button title="Save" onPress={handleSubmit} />
      <Button
        title="Cancel"
        onPress={() => {
          setUpClose();
          props.closeModal();
        }}
      />
    </SafeAreaView>
  );
}
axelcoevas commented 1 year ago

Check the way you're mapping your items ({label: ... , value: ...}), you should be repeating the value %s.

123epsilon commented 1 year ago

Check the way you're mapping your items ({label: ... , value: ...}), you should be repeating the value %s.

When you say %s, in this case do you mean the label? Here it is set to item.title - which I can verify are unique strings. Otherwise the "item" objects are unique Javascript objects but maybe they are being read as just an "Object", and therefore its causing a key collision?

sdg9 commented 1 year ago

@123epsilon set itemKey="label" or whatever property of your object you want used as the key.

123epsilon commented 1 year ago

The above resolved my issue, thank you!