foreign-sapphire
foreign-sapphire11mo ago

What's the best way for data initialization and reuse state data?

I'm using Refine with supabase. I want to have data initialized when the app first load, save those in state, then map that in my componenents when needed without calling the api again. I'm thinking of using useContext and useContext.Provider with useState for the data and setData, wrapping that outside my Refine app. Then create another component called DataInitialization to call the data and setData in Context, like this: // DataInitialization.tsx const DataInitialization: React.FC = () => { const { data, isLoading, isError } = useList<TCountry, HttpError>({ resource: 'dataCountryList' }); const { setData } = useDataCountryList(); useEffect(() => { if (!isLoading && !isError) { console.log('Country List pulled', data.data); setData(data.data); // Additional API calls and state setting can be done here } }, [data, isLoading, isError, setData]); return null; // This component doesn't render anything }; export default DataInitialization; What do you think, is there a better way? Do I really need to install another library? I want to use the existing Refine React Query.
5 Replies
kapa.ai
kapa.ai11mo ago
Hi @lukevo.. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Your approach of using useContext and useContext.Provider with useState for the data and setData is a valid way to manage global state in a React application. However, you might not need to do this if you're using Refine and React Query. Refine uses React Query under the hood for data fetching, which provides a caching mechanism out of the box. When you fetch data using useList, the data is cached and any subsequent calls to useList with the same parameters will retrieve the data from the cache instead of making a new network request. This means you can call useList in any component that needs the data, and it will not result in additional network requests once the data is cached. Here's an example of how you can use useList with caching:
export const BaseElementsList: React.FC<IResourceComponentsProps> = () => {
const [fetch, setFetch] = useState(false);

const { data, isLoading, isError, refetch } = useList<ICourier, HttpError>({
resource: 'base-categories',
enabled: fetch,
});

useEffect(() => {
if (!fetch) {
setFetch(true);
refetch();
}
}, [fetch, refetch]);

if (isLoading) {
return <div>Loading...</div>;
}

if (isError) {
return <div>Something went wrong!</div>;
}
}
export const BaseElementsList: React.FC<IResourceComponentsProps> = () => {
const [fetch, setFetch] = useState(false);

const { data, isLoading, isError, refetch } = useList<ICourier, HttpError>({
resource: 'base-categories',
enabled: fetch,
});

useEffect(() => {
if (!fetch) {
setFetch(true);
refetch();
}
}, [fetch, refetch]);

if (isLoading) {
return <div>Loading...</div>;
}

if (isError) {
return <div>Something went wrong!</div>;
}
}
In this example, a state fetch is used to control when the data is fetched. When the component mounts, if fetch is false, we set it to true and call refetch to fetch the data. Once the data is fetched, any subsequent calls to useList with the same parameters will retrieve the data from the cache. This approach allows you to fetch and cache data at the start of your application, and then use that cached data in your components without additional network requests. You don't need to install another library for this, as it's a feature provided by React Query, which is already used by Refine. Sources: - Discord support thread: invalid hook call error (https://discord.com/channels/837692625737613362/1144003422006288494) - Building a React Admin Panel with refine and daisyUI (https://refine.dev/blog/daisy-ui-react-admin-panel/) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai11mo ago
<@582491401715974144> kapa.ai is still learning and improving, please let us know how it did by reacting below
foreign-sapphire
foreign-sapphire11mo ago
@kapa.ai Thank you, let's help me apply this to my situation. What file should I create, what code should I modify in Appjs, what is the full code for anything that is needed for this to work, let's say I want to call api in <DataInitialization/> and use the data already called in another component. Show me full code for each
kapa.ai
kapa.ai11mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Sure, let's break it down step by step. First, you need to create a new file for your DataInitialization component. Let's call it DataInitialization.tsx. Here's the full code for this component:
// DataInitialization.tsx
import { useList } from "@pankod/refine";
import { useEffect, useState } from "react";

type TCountry = {
// Define your country type here
};

type HttpError = {
// Define your error type here
};

const DataInitialization: React.FC = () => {
const { data, isLoading, isError, refetch } = useList<TCountry, HttpError>({
resource: 'dataCountryList',
enabled: false, // This disables the initial fetch
});

const [fetch, setFetch] = useState(false);

useEffect(() => {
if (!fetch) {
setFetch(true);
refetch();
}
}, [fetch, refetch]);

if (isLoading || isError) {
return null;
}

console.log('Country List pulled', data?.data);

return null; // This component doesn't render anything
};

export default DataInitialization;
// DataInitialization.tsx
import { useList } from "@pankod/refine";
import { useEffect, useState } from "react";

type TCountry = {
// Define your country type here
};

type HttpError = {
// Define your error type here
};

const DataInitialization: React.FC = () => {
const { data, isLoading, isError, refetch } = useList<TCountry, HttpError>({
resource: 'dataCountryList',
enabled: false, // This disables the initial fetch
});

const [fetch, setFetch] = useState(false);

useEffect(() => {
if (!fetch) {
setFetch(true);
refetch();
}
}, [fetch, refetch]);

if (isLoading || isError) {
return null;
}

console.log('Country List pulled', data?.data);

return null; // This component doesn't render anything
};

export default DataInitialization;
In your App.tsx file, you need to include the DataInitialization component at the root level of your application. Here's how you can modify your App.tsx:
// App.tsx
import { Refine } from "@pankod/refine";
import DataInitialization from "./DataInitialization";

const App: React.FC = () => {
return (
<Refine>
<DataInitialization />
{/* Other components */}
</Refine>
);
};

export default App;
// App.tsx
import { Refine } from "@pankod/refine";
import DataInitialization from "./DataInitialization";

const App: React.FC = () => {
return (
<Refine>
<DataInitialization />
{/* Other components */}
</Refine>
);
};

export default App;
Now, in any other component where you need the data, you can use the useList hook with the same parameters to retrieve the cached data. Here's an example:
// SomeComponent.tsx
import { useList } from "@pankod/refine";

type TCountry = {
// Define your country type here
};

type HttpError = {
// Define your error type here
};
const SomeComponent: React.FC = () => {
const { data, isLoading, isError } = useList<TCountry, HttpError>({
resource: 'dataCountryList',
});

if (isLoading) {
return <div>Loading...</div>;
}

if (isError) {
return <div>Something went wrong!</div>;
}

// Use the data here
console.log('Country List', data?.data);

return null;
};

export default SomeComponent;
// SomeComponent.tsx
import { useList } from "@pankod/refine";

type TCountry = {
// Define your country type here
};

type HttpError = {
// Define your error type here
};
const SomeComponent: React.FC = () => {
const { data, isLoading, isError } = useList<TCountry, HttpError>({
resource: 'dataCountryList',
});

if (isLoading) {
return <div>Loading...</div>;
}

if (isError) {
return <div>Something went wrong!</div>;
}

// Use the data here
console.log('Country List', data?.data);

return null;
};

export default SomeComponent;
In this example, useList retrieves the data from the cache, so it doesn't make a new network request. The data is the same data that was fetched in the DataInitialization component. Sources: - Discord support thread: invalid hook call error (https://discord.com/channels/837692625737613362/1144003422006288494) - Building a React Admin Panel with refine and daisyUI (https://refine.dev/blog/daisy-ui-react-admin-panel/) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai11mo ago
<@582491401715974144> kapa.ai is still learning and improving, please let us know how it did by reacting below