'Using function defined in custom hook does not update some value in the state
i recently started using react and i'm trying to write a custom hook used for translating some ui elements. I'm not using a library because it is a larger project and it is expected to have a lot of custom loading/ translating parts.
Goal:
- call the hook in every translatable component (in a very light syntax)
- the hook will return a function used to translate elements in that component
So far, i tried this https://codesandbox.io/s/react-playground-forked-jt90ii?file=/MyComponent.js
Here is the custom hook:
import { useState, useEffect } from "react";
export default function useTranslation({ className, callbackFunction }) {
const [translations, setTranslations] = useState([]);
useEffect(() => {
async function fetchTranslationsForClass(
endpoint,
setTranslations,
className
) {
// HERE WILL BE API CALL
setTranslations([{ code: "HM", value: "Home" }]);
if (callbackFunction) callbackFunction();
}
fetchTranslationsForClass("", setTranslations, className);
}, []);
return [
(code) => {
var a = internalT(translations, code);
return a;
},
translations,
setTranslations
];
}
function internalT(translations, translationCode, interpolationParam) {
var tr = translations.filter((x) => x.code == translationCode);
if (!interpolationParam) return tr && tr[0] && tr[0].value;
else return tr && tr[0] && strInterpolate(tr[0].value);
}
const strInterpolate = (template, args = {}) => {
const interpolateHandler = new Function(
"params",
"const __ = (" +
Object.keys(args).join(",") +
") => `" +
template +
"`\nreturn __(...Object.values(params))"
);
return interpolateHandler(args);
};
That i'm trying to use like this:
import useTranslation from "./useTranslation";
import MyComponent2 from "./MyComponent2.js";
import { useState } from "react";
export default function MyComponent() {
const [t, tr, setTr] = useTranslation("MyComponent", () => {});
const [translatedItems, setTranslatedItems] = useState([{ name: t("HM") }]);
return (
<>
<div>{t("HM")}</div>
<MyComponent2 translatedItems={translatedItems} />
</>
);
}
And it works fine for string embedded in ui but it does not work for a string passed in component state in translatedItems;
In MyComponent2 item.name is always undefined:
export default function MyComponent2({ translatedItems }) {
return (
<>
{translatedItems.map((item, index) => {
return (
<>
<div>{"index" + index}</div>
<div key={index}> {"'" + item.name + "'"}</div>
</>
);
})}
</>
);
}
Basically the state is initialized at first render and it does not update after the 't' function is defined; If i try to set the state with useEffect this will create an infinite loop.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|