robust-apricot
robust-apricot13h ago

add if don't exist

Can i do something like looking for elements in the api, if the response is empty array i update and add element to the api. using Strapi
17 Replies
kapa.ai
kapa.ai13h ago
Hi @SetiZ. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the provided knowledge sources, Refine does not offer a built-in, single-step method to "update if exists, otherwise add" (commonly known as "upsert") for Strapi or other data providers. The standard approach in Refine is to: 1. Query for the element using a data hook like useOne, useList, or a custom query. 2. Check if the response is empty (i.e., the element does not exist). 3. If empty, create the element using useCreate. 4. If found, update the element using useUpdate. Here’s a conceptual example of how you might implement this logic in a React component using Refine hooks:
import { useList, useCreate, useUpdate } from "@refinedev/core";

const resource = "your-resource";
const searchParams = { /* your search/filter params */ };

const { data: listData } = useList({ resource, filters: [/* your filters */] });
const { mutate: create } = useCreate();
const { mutate: update } = useUpdate();

const upsertElement = (element) => {
if (listData && listData.length === 0) {
// Element does not exist, create it
create({ resource, values: element });
} else if (listData && listData.length > 0) {
// Element exists, update it (assuming first match)
update({ resource, id: listData[0].id, values: element });
}
};
import { useList, useCreate, useUpdate } from "@refinedev/core";

const resource = "your-resource";
const searchParams = { /* your search/filter params */ };

const { data: listData } = useList({ resource, filters: [/* your filters */] });
const { mutate: create } = useCreate();
const { mutate: update } = useUpdate();

const upsertElement = (element) => {
if (listData && listData.length === 0) {
// Element does not exist, create it
create({ resource, values: element });
} else if (listData && listData.length > 0) {
// Element exists, update it (assuming first match)
update({ resource, id: listData[0].id, values: element });
}
};
Important notes: - You must first fetch the data to determine existence. - Strapi and Refine do not provide an atomic "upsert" operation out of the box. - This approach may have race conditions in highly concurrent environments. If you need true atomic upsert, you would have to implement a custom endpoint in your Strapi backend. Summary:
You can implement "update if exists, otherwise add" logic in Refine by first querying for the element, then conditionally calling either useUpdate or useCreate based on whether the element exists. There is no built-in upsert method in Refine or the Strapi data provider according to the current documentation and knowledge sources provided. See data hooks and update example ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13h ago
<@267689263246606336> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
robust-apricot
robust-apricotOP13h ago
@kapa.ai no update, just create a new line. also need to call an external api to get the data to insert
kapa.ai
kapa.ai13h ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You can implement the logic you described—fetching data from an external API, checking if it exists in your Strapi backend, and creating a new record if it does not exist—using Refine's data hooks. However, Refine does not provide a built-in, single-step method for this; you need to orchestrate the steps manually in your component logic. Here’s how you can approach it, based on the knowledge sources: 1. Call the external API using your preferred method (e.g., fetch or axios) to get the data you want to insert. 2. Check if the data exists in Strapi by using a data hook like useList with appropriate filters. 3. If the data does not exist (empty array), create a new record in Strapi using the useCreate hook. Here is a conceptual example:
import { useList, useCreate } from "@refinedev/core";
import { useEffect } from "react";
import axios from "axios";

const resource = "your-resource";
const externalApiUrl = "<https://external.api/data";>

const MyComponent = () => {
const { data: listData } = useList({
resource,
filters: [
// your filter logic to check for existence
],
});
const { mutate: create } = useCreate();

useEffect(() => {
const fetchAndInsert = async () => {
// 1. Call external API
const { data: externalData } = await axios.get(externalApiUrl);

// 2. Check if data exists in Strapi (listData)
if (listData && listData.length === 0) {
// 3. If not, create a new record in Strapi
create({ resource, values: externalData });
}
};

fetchAndInsert();
}, [listData, create]);

return null;
};
import { useList, useCreate } from "@refinedev/core";
import { useEffect } from "react";
import axios from "axios";

const resource = "your-resource";
const externalApiUrl = "<https://external.api/data";>

const MyComponent = () => {
const { data: listData } = useList({
resource,
filters: [
// your filter logic to check for existence
],
});
const { mutate: create } = useCreate();

useEffect(() => {
const fetchAndInsert = async () => {
// 1. Call external API
const { data: externalData } = await axios.get(externalApiUrl);

// 2. Check if data exists in Strapi (listData)
if (listData && listData.length === 0) {
// 3. If not, create a new record in Strapi
create({ resource, values: externalData });
}
};

fetchAndInsert();
}, [listData, create]);

return null;
};
Key points: - You must handle the external API call yourself (Refine does not abstract this). - The check for existence is done via useList and filters. - The creation is done via useCreate if the list is empty. There is no built-in "create if not exists" or "upsert" in Refine or the Strapi data provider, so this manual orchestration is required.
See useCreate documentation ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13h ago
<@267689263246606336> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
robust-apricot
robust-apricotOP13h ago
@kapa.ai can I use useCustom instead of fetch here?
kapa.ai
kapa.ai13h ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, you can use Refine's useCustom hook instead of a direct fetch call to make requests to an external API. The useCustom hook is designed for sending custom queries to any endpoint, not just your main data provider, and supports specifying the URL, HTTP method, headers, query parameters, and more. The response will be managed with React Query, giving you features like caching and loading states. Here’s a basic example of how you might use useCustom to call an external API:
import { useCustom } from "@refinedev/core";

const { data, isLoading, error } = useCustom({
url: "<https://external.api/data",>
method: "get",
// You can add config: { headers, query, ... } if needed
});
import { useCustom } from "@refinedev/core";

const { data, isLoading, error } = useCustom({
url: "<https://external.api/data",>
method: "get",
// You can add config: { headers, query, ... } if needed
});
You can then use the data from this hook in your logic to check if it exists in Strapi and, if not, create a new record. Summary:
useCustom is a suitable and recommended alternative to fetch for custom API requests in Refine, as described in the documentation and examples provided here and here. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13h ago
<@267689263246606336> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
robust-apricot
robust-apricotOP13h ago
@kapa.ai can i put useCustom inside the useEffect?
kapa.ai
kapa.ai13h ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You should not call the useCustom hook (or any React hook) inside a useEffect. According to the Rules of Hooks, hooks must be called at the top level of your React function component, not inside loops, conditions, or nested functions like useEffect. This rule applies to all hooks, including useCustom. If you call a hook inside useEffect, you will get a warning or error similar to:
Warning: Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. You can only call Hooks at the top level of your React function.
This is confirmed by a GitHub issue where such usage led to warnings in the console. Correct usage:
Call useCustom at the top level of your component, and use useEffect for imperative logic if needed, but not for calling hooks themselves.
// Correct usage
const { data, isLoading } = useCustom({ ... });

useEffect(() => {
if (data) {
// Do something with the data
}
}, [data]);
// Correct usage
const { data, isLoading } = useCustom({ ... });

useEffect(() => {
if (data) {
// Do something with the data
}
}, [data]);
Summary:
Do not put useCustom inside useEffect. Always call hooks at the top level of your component, not inside other hooks or functions.
See related issue and warning ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13h ago
<@267689263246606336> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
robust-apricot
robust-apricotOP13h ago
@kapa.ai how can i make it call only in the useeffect and not on the component, or should I use fetch instead?
kapa.ai
kapa.ai13h ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You cannot use useCustom (or any React hook) only inside a useEffect—hooks must be called at the top level of your component, not conditionally or inside other functions like useEffect. This is a fundamental React rule and is confirmed in the knowledge sources, which show useCustom being used at the top level of the component, not inside useEffect or any other function block useCustom documentation. If you need to trigger a request only in response to an event (such as a button click or inside an effect), you have two main options: 1. Use useCustom with queryOptions: { enabled: false } and call refetch manually:
This pattern allows you to control when the request is made, similar to how you would use fetch inside useEffect. You initialize the hook at the top level, but the request only fires when you call refetch (for example, inside a useEffect or event handler).
const { data, refetch } = useCustom({
url: "<https://external.api/data",>
method: "get",
queryOptions: { enabled: false }, // disables automatic fetch
});

useEffect(() => {
// Call refetch when you want to trigger the request
refetch();
}, []);

const { data, refetch } = useCustom({
url: "<https://external.api/data",>
method: "get",
queryOptions: { enabled: false }, // disables automatic fetch
});

useEffect(() => {
// Call refetch when you want to trigger the request
refetch();
}, []);

This approach is also recommended in community discussions and GitHub issues for cases where you want to trigger a request manually GitHub Issue #2407. 2. Use fetch or another data-fetching library directly inside useEffect:
If you want full imperative control and do not need React Query's features, you can use fetch or axios inside useEffect as shown in the knowledge sources Next.js data fetching blog. Summary:
- Do not call useCustom inside useEffect. - To trigger a request only in useEffect, use useCustom with enabled: false and call refetch inside your effect. - Alternatively, use fetch directly in useEffect if you do not need React Query features. This approach is supported and recommended in the official documentation and community discussions. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13h ago
<@267689263246606336> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
robust-apricot
robust-apricotOP8h ago
@kapa.ai when i call refetch, can I add an argument for useCustom tu use in the query?
kapa.ai
kapa.ai8h ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- When you call refetch from the useCustom hook, you cannot pass new arguments directly to refetch to change the query parameters. The useCustom hook's refetch function will use the parameters (such as url, method, and config) that were initially provided when the hook was created. If you want to change the query parameters (for example, to use a different query or payload), you need to update the props passed to useCustom (such as changing the config.query or config.payload), which will cause the hook to re-run with the new parameters. This is the standard pattern in Refine and is shown in the documentation and examples:
When properties are changed, the useCustom hook will trigger a new request.
useCustom documentation
Example:
const [query, setQuery] = useState({ title: "Foo bar" });

const { data, refetch } = useCustom({
url: "<https://api.example.com/items",>
method: "get",
config: { query },
queryOptions: { enabled: false },
});

// To change the query, update the state:
setQuery({ title: "New Title" });
// Then call refetch() to fetch with the new query
refetch();
const [query, setQuery] = useState({ title: "Foo bar" });

const { data, refetch } = useCustom({
url: "<https://api.example.com/items",>
method: "get",
config: { query },
queryOptions: { enabled: false },
});

// To change the query, update the state:
setQuery({ title: "New Title" });
// Then call refetch() to fetch with the new query
refetch();
Summary:
- You cannot pass arguments directly to refetch in useCustom. - To change the query, update the hook's props (e.g., state for config.query), then call refetch() to trigger the request with the new parameters. This behavior is consistent with the documentation and examples provided for useCustom in Refine. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai8h ago
<@267689263246606336> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?