React-select: Still having issues with unique key error when using object values

Created on 23 Jul 2018  Â·  8Comments  Â·  Source: JedWatson/react-select

Using 2.0.0, I am still getting an error when I use object values with string labels.

This is the error I get:

Warning: Encountered two children with the same key,[object Object]. 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.

I created a sandbox showing the behavior here.

Just select 'Option1' and 'Option 2' and it will emit the error to the console.

Most helpful comment

Looks like the value should not be an object. Try to provide options like this: { value: "Option 1", label: "Option 1", data: new Firm({ legalName: "Option 1" }) },

And then use the data field to access your object, and value would contain some unique key. Worked in my case to get rid of these warnings.

All 8 comments

I'm no expert, but taking a look at your example makes me assume that it's coercing the value property to a string or something like that (hence [object Object] ?) which wouldn't be unique. what you can do is set the values to be e.g. 1, 2, 3 and then add an additional property called firm that is the Firm object

I modified the code sandbox to better mirror my objects. There is an override of the toString method in my code that stringifies the JSON. I put a simpler version in the sandbox, but it has the same effect.

get [Symbol.toStringTag]() {
  return this._legalName; 
}

Same issue. Actually, if the code DID call toString() it would solve my problem, because the JSON-ified version would definitely be unique.

A better way might be to have a property called uniqueKey, which would be the name of a property on the object that uniquely identifies it.

<Select className="basic-single" classNamePrefix="select" isMulti={true} name="firm" options={firmOptions} uniqueKey="firmId" />

In the component's code, the react key variable would then map to value[uniqueKey].

I'm not sure I follow you with the additional property bit. What would I add the property to?

I can see using a unique ID as the value, then using that to lookup the value when the event is called, but that is very inefficient (there are thousands of values right now, there will be many more soon).

Looks like the value should not be an object. Try to provide options like this: { value: "Option 1", label: "Option 1", data: new Firm({ legalName: "Option 1" }) },

And then use the data field to access your object, and value would contain some unique key. Worked in my case to get rid of these warnings.

Hi, the issues seems to be still open as I'm facing it. @robotanz suggestion seems fine but still I think it is good to have a fix in the repo itself. Can a prop like toString or customKey be passed so when it's provided something like customKey(value) be set instead of value itself as the key?
I think that's the simple solution for fixing this bug.

I found that if I define getOptionValue, I can still keep the value an object but have react-select generate unique keys for the options.

For example, I am doing something like this:

const TestSelect = props => {
  const { testOptions } = props;

  const options = testOptions.map(test =>
      ({label: test.name, value: {id: test.id, name: test.name}})
    )

  const getOptionValue = option => option.value.id;

  const handleChange = option => setValue(option.value)

  return (
    <Select {...{ ...props, options, getOptionValue, handleChange }} />
  );
};

to solve this: I just added a toString() method in the objects I pass as a value to react-select, so I can tell it how to create a key for that specific value

/** useSpreadsheetData.ts */
import { useEffect, useState } from "react"
import { parse } from "papaparse"

type Entry = {
    view_name: string
    field_name: string
    table_name: string
}

const url = "someurl"

export const useSpreadsheetData = () => {
    const [state, setState] = useState<ReadonlyArray<Entry>>([])

    useEffect(
        () =>
            parse(url, {
                header: true,
                download: true,
                complete: response => setState(response.data),
            }),
        []
    )

    return state
}
/** SelectFields.tsx */
import * as React from "react"
import Select from "react-select"
import { useSpreadsheetData } from "./useSpreadsheetData"

export const SelectFields = props => {
    const state = useSpreadsheetData()

    return (
        <Select
            isMulti
            onChange={props.onChange}
            options={state.map(value => ({
                value: {
                    ...value,
                    /**
                     * The method above is to avoid React Select from spamming
                     * the console with key errors since it is using this object
                     * as a value for every select option
                     **/
                    toString: () => `${value.field_name}-${value.view_name}`,
                },
                label: `${value.table_name} (${value.view_name})`,
            }))}
        />
    )
}

Hello -

In an effort to sustain the react-select project going forward, we're closing old issues.

We understand this might be inconvenient but in the best interest of supporting the broader community we have to direct our efforts towards the current major version.

If you aren't using the latest version of react-select please consider upgrading to see if it resolves any issues you're having.

However, if you feel this issue is still relevant and you'd like us to review it - please leave a comment and we'll do our best to get back to you!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

x-yuri picture x-yuri  Â·  3Comments

sampatbadhe picture sampatbadhe  Â·  3Comments

geraldfullam picture geraldfullam  Â·  3Comments

mjuopperi picture mjuopperi  Â·  3Comments

MindRave picture MindRave  Â·  3Comments