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;
2
Answers
I solved it by using useEffect. Which I don't like and would gladly accept some other finer solutions.
To quote the docs on the
initialState
foruseState()
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 ift("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 setteruseState()
returns.Instead, update your state to hold your translation key:
Then grab the translation when you render:
this will also mean that
NumberFilterSelect
should provide a translation key rather than a raw label to itshandleLabelChange
callback.