other-emerald
other-emerald2w ago

How to implement InfiniteSelect correctly?

I am using the following code to generate and fill a Select in an Edit.
export const InfiniteSelect: React.FC<EndlessSelectProps> = ({ resource, optionLabel, optionValue, defaultValue }) => {
const [page, setPage] = useState<number>(1);
const [options, setOptions] = useState<SelectProps["options"]>([]);
const [search, setSearch] = useState<string>("");
const hasMore = useRef(true)

const onSuccess = (data: any) => {
if (!data.data?.length) {
hasMore.current = false;
}

const normalizedData = data.data?.map((item: any) => ({
label: String(item[optionLabel]),
value: String(item[optionValue]),

}));

if (!search?.length) {
setOptions((prev) => [...(prev || []), ...normalizedData]);
} else {
setOptions(normalizedData);
}
}


const { selectProps } = useSelect({
resource: resource,
fetchSize: 20,
pagination: { current: page },
defaultValue: defaultValue,

queryOptions: {
keepPreviousData: true,
onSuccess: onSuccess,
},

defaultValueQueryOptions: {
keepPreviousData: true,
onSuccess: onSuccess,
},
onSearch: (value) => {
setPage(1);
hasMore.current = true;
setSearch(value);

return [
{
field: optionLabel,
operator: "eq",
value,
},
];
},

});
return <Select {...selectProps} defaultValue={String(defaultValue)} />
}
export const InfiniteSelect: React.FC<EndlessSelectProps> = ({ resource, optionLabel, optionValue, defaultValue }) => {
const [page, setPage] = useState<number>(1);
const [options, setOptions] = useState<SelectProps["options"]>([]);
const [search, setSearch] = useState<string>("");
const hasMore = useRef(true)

const onSuccess = (data: any) => {
if (!data.data?.length) {
hasMore.current = false;
}

const normalizedData = data.data?.map((item: any) => ({
label: String(item[optionLabel]),
value: String(item[optionValue]),

}));

if (!search?.length) {
setOptions((prev) => [...(prev || []), ...normalizedData]);
} else {
setOptions(normalizedData);
}
}


const { selectProps } = useSelect({
resource: resource,
fetchSize: 20,
pagination: { current: page },
defaultValue: defaultValue,

queryOptions: {
keepPreviousData: true,
onSuccess: onSuccess,
},

defaultValueQueryOptions: {
keepPreviousData: true,
onSuccess: onSuccess,
},
onSearch: (value) => {
setPage(1);
hasMore.current = true;
setSearch(value);

return [
{
field: optionLabel,
operator: "eq",
value,
},
];
},

});
return <Select {...selectProps} defaultValue={String(defaultValue)} />
}
The above select is then embedded with the following code:
export const IdEdit: React.FC<FormProp & { lineitemsData: any }> = ({ lineitemsData, ...props }) => {
return (
<Form.Item {...props} name="invoice_id" required={true}>
<InfiniteSelect defaultValue={lineitemsData?.invoice_id} resource="invoices" optionLabel="id" optionValue="id" />
</Form.Item>)
}
export const IdEdit: React.FC<FormProp & { lineitemsData: any }> = ({ lineitemsData, ...props }) => {
return (
<Form.Item {...props} name="invoice_id" required={true}>
<InfiniteSelect defaultValue={lineitemsData?.invoice_id} resource="invoices" optionLabel="id" optionValue="id" />
</Form.Item>)
}
The field is correctly loads data and search works. But saving the resource does not update the field, i.e. onFinish receives only the old value for the invoice_id.
2 Replies
kapa.ai
kapa.ai2w ago
Hi @jonas. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To implement an InfiniteSelect correctly in your Refine application, you need to ensure that the useSelect hook is properly configured and that the Select component is correctly integrated within your form. Based on the provided code and the knowledge sources, here is a refined approach to ensure that the Select component updates correctly and the form submission captures the updated value. Step-by-Step Implementation 1. Define the InfiniteSelect Component: Ensure that the InfiniteSelect component is correctly set up to handle pagination and search functionality. The provided code looks mostly correct, but let's ensure it aligns with best practices.
import React, { useState, useRef } from "react";
import { Select } from "antd";
import { useSelect } from "@pankod/refine-core";

export const InfiniteSelect: React.FC<EndlessSelectProps> = ({ resource, optionLabel, optionValue, defaultValue }) => {
const [page, setPage] = useState<number>(1);
const [options, setOptions] = useState<SelectProps["options"]>([]);
const [search, setSearch] = useState<string>("");
const hasMore = useRef(true);

const onSuccess = (data: any) => {
if (!data.data?.length) {
hasMore.current = false;
}

const normalizedData = data.data?.map((item: any) => ({
label: String(item[optionLabel]),
value: String(item[optionValue]),
}));

if (!search?.length) {
setOptions((prev) => [...(prev || []), ...normalizedData]);
} else {
setOptions(normalizedData);
}
};
const { selectProps } = useSelect({
resource: resource,
fetchSize: 20,
pagination: { current: page },
defaultValue: defaultValue,
queryOptions: {
keepPreviousData: true,
onSuccess: onSuccess,
},
defaultValueQueryOptions: {
keepPreviousData: true,
onSuccess: onSuccess,
},
onSearch: (value) => {
setPage(1);
hasMore.current = true;
setSearch(value);

return [
{
field: optionLabel,
operator: "eq",
value,
},
];
},
});

return <Select {...selectProps} defaultValue={String(defaultValue)} />;
};

import React, { useState, useRef } from "react";
import { Select } from "antd";
import { useSelect } from "@pankod/refine-core";

export const InfiniteSelect: React.FC<EndlessSelectProps> = ({ resource, optionLabel, optionValue, defaultValue }) => {
const [page, setPage] = useState<number>(1);
const [options, setOptions] = useState<SelectProps["options"]>([]);
const [search, setSearch] = useState<string>("");
const hasMore = useRef(true);

const onSuccess = (data: any) => {
if (!data.data?.length) {
hasMore.current = false;
}

const normalizedData = data.data?.map((item: any) => ({
label: String(item[optionLabel]),
value: String(item[optionValue]),
}));

if (!search?.length) {
setOptions((prev) => [...(prev || []), ...normalizedData]);
} else {
setOptions(normalizedData);
}
};
const { selectProps } = useSelect({
resource: resource,
fetchSize: 20,
pagination: { current: page },
defaultValue: defaultValue,
queryOptions: {
keepPreviousData: true,
onSuccess: onSuccess,
},
defaultValueQueryOptions: {
keepPreviousData: true,
onSuccess: onSuccess,
},
onSearch: (value) => {
setPage(1);
hasMore.current = true;
setSearch(value);

return [
{
field: optionLabel,
operator: "eq",
value,
},
];
},
});

return <Select {...selectProps} defaultValue={String(defaultValue)} />;
};

2. Integrate InfiniteSelect in the Form: Ensure that the InfiniteSelect component is correctly integrated within the form and that the form captures the updated value on submission.
import React from "react";
import { Form } from "antd";
import { InfiniteSelect } from "./InfiniteSelect"; // Adjust the import path as necessary

export const IdEdit: React.FC<FormProp & { lineitemsData: any }> = ({ lineitemsData, ...props }) => {
return (
<Form.Item {...props} name="invoice_id" required={true}>
<InfiniteSelect defaultValue={lineitemsData?.invoice_id} resource="invoices" optionLabel="id" optionValue="id" />
</Form.Item>
);
};

import React from "react";
import { Form } from "antd";
import { InfiniteSelect } from "./InfiniteSelect"; // Adjust the import path as necessary

export const IdEdit: React.FC<FormProp & { lineitemsData: any }> = ({ lineitemsData, ...props }) => {
return (
<Form.Item {...props} name="invoice_id" required={true}>
<InfiniteSelect defaultValue={lineitemsData?.invoice_id} resource="invoices" optionLabel="id" optionValue="id" />
</Form.Item>
);
};

3. Ensure Form Submission Captures Updated Value: Make sure that the form's onFinish handler is correctly set up to capture the updated value of invoice_id. ```tsx import React from "react"; import { Form, Button } from "antd"; import { IdEdit } from "./IdEdit"; // Adjust the import path as necessary ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@1262429313710559314> kapa.ai is still learning and improving, please let us know how it did by reacting below