other-emerald
other-emerald12mo ago

Default query result duplicates the options of select options.

Previously I have asked a question regarding how to create a custom option in select input https://discord.com/channels/837692625737613362/1037681220487741440 and implemented a solution provided by @Omer. But now I have an issue with that process as my default query populates the options value with other options which results the same value being shown twice. For example I have a useSelect hook to get a data as below:
const { queryResult, defaultValueQueryResult } = useSelect<ISeatlayout>({
resource: "buslayouts",
optionLabel: "structure",
defaultValue: record?.bus_layouts || [],

pagination: {
mode: "server",
pageSize: 100
}
});

const allLayoutOptions = [
...(queryResult?.data?.data || []),
...(defaultValueQueryResult?.data?.data || [])
];
const { queryResult, defaultValueQueryResult } = useSelect<ISeatlayout>({
resource: "buslayouts",
optionLabel: "structure",
defaultValue: record?.bus_layouts || [],

pagination: {
mode: "server",
pageSize: 100
}
});

const allLayoutOptions = [
...(queryResult?.data?.data || []),
...(defaultValueQueryResult?.data?.data || [])
];
Here in my allLayoutOptions the data will be populate twice as I get the value from queryResult and the same value from the defaultValueQueryResult, is there a better solution you can suggest me? Or else I am thinking of a solution as to filter out the duplicated value from allLayoutOptions. Is this the solution that I should move on with?
4 Replies
kapa.ai
kapa.ai12mo ago
Hi @dipbazz. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Yes, you're on the right track. The issue you're facing is due to the fact that both queryResult and defaultValueQueryResult might contain the same data, leading to duplicates in your allLayoutOptions. A simple solution would be to filter out the duplicates from allLayoutOptions. You can achieve this by creating a new array from a Set, which automatically removes duplicates because it only allows unique values. Here's how you can do it:
const allLayoutOptions = [
...(queryResult?.data?.data || []),
...(defaultValueQueryResult?.data?.data || [])
];

const uniqueLayoutOptions = Array.from(new Set(allLayoutOptions.map(a => a.id)))
.map(id => {
return allLayoutOptions.find(a => a.id === id)
});
const allLayoutOptions = [
...(queryResult?.data?.data || []),
...(defaultValueQueryResult?.data?.data || [])
];

const uniqueLayoutOptions = Array.from(new Set(allLayoutOptions.map(a => a.id)))
.map(id => {
return allLayoutOptions.find(a => a.id === id)
});
In this code, we first create a Set from the ids of the items in allLayoutOptions. The Set will automatically remove any duplicate ids. Then we map through the unique ids and find the corresponding item from allLayoutOptions. This will give you an array of unique items from allLayoutOptions. However, please note that this solution assumes that the id field in your data is unique. If it's not, you'll need to adjust the code to use a unique field. Also, keep in mind that this is a client-side solution and it might not be the most efficient way if you're dealing with a large amount of data. If that's the case, you might want to consider handling this on the server-side. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai12mo ago
<@494653850632978472> kapa.ai is still learning and improving, please let us know how it did by reacting below
metropolitan-bronze
metropolitan-bronze12mo ago
Hey @dipbazz, We investigated this issue and decided to add a new type like (item: TData) => string to support this feature. For example, the user combines firstName and lastName into a single optionLabel field like this:
useSelect({
optionLabel: (item) => `${item.firstName} ${item.lastName}`,
});
useSelect({
optionLabel: (item) => `${item.firstName} ${item.lastName}`,
});
Also, the user can set optionValue like this:
useSelect({
optionValue: (item) => item.foo.id,
});
useSelect({
optionValue: (item) => item.foo.id,
});
Of course, to provide backward compatibility, we need to hold the string type for optionLabel and optionValue properties. In this way, we can avoid the problem of duplicate options. Because the useSelect already uses the lodash/uniqBy function to remove duplicate options. Could you want to open a PR for this feature? If you don't have time, you can use the lodash/uniqBy function to remove duplicate options as a temporary solution. Additionally, you can see it how we use lodash/uniqBy function in the useSelect hook source code.
other-emerald
other-emerald12mo ago
Hey @salihozdemir, here is the issues for a feature request https://github.com/refinedev/refine/issues/4880
GitHub
[FEAT] custom optionLabel and remove duplicate list in useSelect ho...
Is your feature request related to a problem? Please describe. I wanted to add a custom optionLabel in useSelect hook which I couldn't manipulate in useSelect options, @omeraplak have helped me...