I have an input with a label. The label has some translations as well as some variations that happen depending on which page the user is so I put translation keys inside useState
to watch changes and react to them by changing the label text. The problem is when I pass the translation key to useState and change language, the text inside useState doesn't translate.
I marked the useState
in question with **.
import CloseIcon from "@mui/icons-material/Close";
import SearchIcon from "@mui/icons-material/Search";
import { Box, IconButton, TextField } from "@mui/material";
import { useGetTableData } from "hooks/useGetTableData";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import NumberFilterSelect from "./NumberFilterSelect";
const NumberFilter = () => {
const { refetch, query, isInvoices, findOne } = useGetTableData();
const { t } = useTranslation();
const [Number, setNumber] = useState("");
const handleInputChange = (e) => setNumber(e.target.value);
**const [label, setLabel] = useState(t("invoice.lookup.labelinvoiceNo"));**
const handleLabelChange = (label) => setLabel(label);
const handleFilterByNumber = () => {
if (Number === "") return;
findOne({
customerId: query.customerId,
[`${isInvoices ? "invoiceNumber" : "orderNumber"}`]: Number,
});
};
const clearNumberFilter = () => {
refetch();
setNumber("");
};
return (
<Box
sx={(theme) => ({
display: "flex",
backgroundColor: theme.palette.inputBackgroundColor.main,
border: `1px solid ${theme.palette.inputBorderColor.main}`,
borderRadius: "4px",
"&:hover": {
background: "#e7e7e7",
},
})}
>
<TextField
label={label}
value={Number}
onChange={handleInputChange}
variant="filled"
onKeyDown={(e) => e.key === "Enter" && handleFilterByNumber()}
sx={{
width: "100%",
"& .MuiInputBase-root": {
background: "none",
border: "none",
},
}}
InputLabelProps={{ shrink: true }}
InputProps={{
endAdornment: (
<IconButton onClick={handleFilterByNumber}>
<SearchIcon />
</IconButton>
),
disableUnderline: true,
sx: {
background: "none",
borderRadius: 0,
"&:hover": {
background: "none",
},
},
}}
/>
{isInvoices && (
<NumberFilterSelect handleLabelChange={handleLabelChange} />
)}
<Box
sx={(theme) => ({
display: "flex",
borderLeft: `1px solid ${theme.palette.inputBorderColor.main}`,
})}
>
<IconButton
onClick={clearNumberFilter}
sx={{
"&:hover": {
background: "none",
},
}}
>
<CloseIcon />
</IconButton>
</Box>
</Box>
);
};
export default NumberFilter;
To quote the docs on the initialState
for useState()
This argument is ignored after the initial render.
which can be a good thing - if React updated your state each time it rerendered to be the new initialState
then you wouldn't be able to set a new state value as it would keep getting reset. So even if t("invoice.lookup.labelinvoiceNo")
changes, your state won't reflect that new value. The only way to persistently update your state is through using the state setter useState()
returns.
Instead, update your state to hold your translation key:
const [labelKey, setLabelKey] = useState("invoice.lookup.labelinvoiceNo");
Then grab the translation when you render:
<TextField label={t(labelKey)} ... />
this will also mean that NumberFilterSelect
should provide a translation key rather than a raw label to its handleLabelChange
callback.