eastern-cyan
eastern-cyanβ€’2y ago

make a new call api after the x-locale change

Hello i'm currently making an app with refine and i have implement i18n. I also have an API which allow me to fetch data in french and in english accord to "x-locale" in REST request header. I would like to know how can i make a new api call without refreshing the page ?
52 Replies
environmental-rose
environmental-roseβ€’2y ago
Hi @harisris, All the data related hooks returns refetch functionality. for example;
const { tableProps, tableQueryResult } = useTable<IPost>();
tableQueryResult.refetch();
const { tableProps, tableQueryResult } = useTable<IPost>();
tableQueryResult.refetch();
u can call this tableQueryResult.refetch()
eastern-cyan
eastern-cyanβ€’2y ago
Hi Alican, thank you for your response !! I am using a DataGrid component and i use a useDataGrid hook. I do not find any refetch function for this hook. How can I make it work with useDataGrid or does any other solution exist ?
environmental-rose
environmental-roseβ€’2y ago
it's inside tableQueryResult object.
const { tableProps, tableQueryResult } = useDataGrid();
tableQueryResult.refetch();
const { tableProps, tableQueryResult } = useDataGrid();
tableQueryResult.refetch();
eastern-cyan
eastern-cyanβ€’2y ago
Finnaly this does the refetch but the request has the same header. I put the tableQueryResult.refetch(); inside a useEffect triggered when the locale change and nothing change. Does this functionnality just replay the last request ?
environmental-rose
environmental-roseβ€’2y ago
Yes, It's refetching with current values. I tested this code snippet. it's work as expected. what is your implementation look like ?
const [xLocale, setXLocale] = useState("locale-1");

const { tableProps, tableQueryResult } = useDataGrid({
metaData: {
headers: { "x-locale": xLocale },
},
});

useEffect(() => {
tableQueryResult.refetch();
}, [xLocale]);
const [xLocale, setXLocale] = useState("locale-1");

const { tableProps, tableQueryResult } = useDataGrid({
metaData: {
headers: { "x-locale": xLocale },
},
});

useEffect(() => {
tableQueryResult.refetch();
}, [xLocale]);
eastern-cyan
eastern-cyanβ€’2y ago
const currentLanguage = i18n.language;
const {dataGridProps, tableQueryResult} = useDataGrid<IDomains>({
hasPagination: false,
});
useEffect(() => {
tableQueryResult.refetch();
}, [currentLanguage]);
const currentLanguage = i18n.language;
const {dataGridProps, tableQueryResult} = useDataGrid<IDomains>({
hasPagination: false,
});
useEffect(() => {
tableQueryResult.refetch();
}, [currentLanguage]);
i will try your code
environmental-rose
environmental-roseβ€’2y ago
where do you set headers ?
eastern-cyan
eastern-cyanβ€’2y ago
the headers are set in an other component but the set work fine when i refresh the page the request is made with the right header
export const LanguageSelector: React.FC = () => {
const {i18n} = useTranslation();
const changeLanguage = useSetLocale();
const locale = useGetLocale();
const currentLocale = locale();
/**
* return the current language
* @param lang current language
*/
const selectedLanguage = (lang: string) => {
if (lang === "fr-FR") return "https://flagcdn.com/fr.svg";
else if (lang === "en") return "https://flagcdn.com/gb.svg";
};
return (
<>
<TextField
select
value={currentLocale}
onChange={(e) => {
changeLanguage(e.target.value);
}}
className="language-selector"
size="small"
>
{i18n.languages.map((lang) => (
<MenuItem key={lang} value={lang}>
<span className="language-selector-image">
<img
alt="flag"
src={selectedLanguage(lang)}
loading="lazy"
width="30"
/>
<p>{lang === "en" ? "English" : "Français"}</p>
</span>
</MenuItem>
))}
</TextField>
</>
);
};
export const LanguageSelector: React.FC = () => {
const {i18n} = useTranslation();
const changeLanguage = useSetLocale();
const locale = useGetLocale();
const currentLocale = locale();
/**
* return the current language
* @param lang current language
*/
const selectedLanguage = (lang: string) => {
if (lang === "fr-FR") return "https://flagcdn.com/fr.svg";
else if (lang === "en") return "https://flagcdn.com/gb.svg";
};
return (
<>
<TextField
select
value={currentLocale}
onChange={(e) => {
changeLanguage(e.target.value);
}}
className="language-selector"
size="small"
>
{i18n.languages.map((lang) => (
<MenuItem key={lang} value={lang}>
<span className="language-selector-image">
<img
alt="flag"
src={selectedLanguage(lang)}
loading="lazy"
width="30"
/>
<p>{lang === "en" ? "English" : "Français"}</p>
</span>
</MenuItem>
))}
</TextField>
</>
);
};
here is the component which change the locale
environmental-rose
environmental-roseβ€’2y ago
I undestand. refine uses react-query under the hood. and actually headers out of scope for react-query. we need to use fetch library with react-query like axios or window.fetch our examples uses react query with axios. and we have implementation for passing headers with data hooks. for example: useDataGrid takes metaData, and passing to react-query and react-query passes to axios. in this situtation. you need to write this useEffect and metaData to everywhere. actually it's a bad implementation let me think what we can do. i have couple ideas https://refine.dev/docs/api-reference/core/hooks/invalidate/useInvalidate/ with this, you can invalidate all queries. you don't need to useEffect and refetch. I thought you would only use it once.
invalidate({
dataProviderName: "your-data-provider-name",
invalidates: ["all"],
});
invalidate({
dataProviderName: "your-data-provider-name",
invalidates: ["all"],
});
you can do that after language changed
eastern-cyan
eastern-cyanβ€’2y ago
Ok i'm going to try
environmental-rose
environmental-roseβ€’2y ago
but before do that, we need to set x-locale header are you using axios with custom data provider?
eastern-cyan
eastern-cyanβ€’2y ago
ok ok i try and i get back to you yes i'm using axios
environmental-rose
environmental-roseβ€’2y ago
we have couple of options to do that. you can search on google like "how to set dynamically axios headers" but this is the easiest way for me. you can get xLocale before each request.
axiosInstance.interceptors.request.use(config => {
config.headers.put['x-locale'] = localStorage.getItem('x-locale');
return config;
});
axiosInstance.interceptors.request.use(config => {
config.headers.put['x-locale'] = localStorage.getItem('x-locale');
return config;
});
but dont forget. you need to call invalidate after modify the localeStorage
eastern-cyan
eastern-cyanβ€’2y ago
actually the language is set correctly in the localStorage and it change when i change it with the select component
environmental-rose
environmental-roseβ€’2y ago
nice, but we need to update default axios headers after you change locale or you can set x-locale header before every request with axios interceptors