const MyComponent = () => {
const [avaliador, setAvaliador] = useState("");
const [avaliadoresList, setAvaliadoresList] = useState([]);
const [DataResultsTotal, setDataResultsTotal] = useState([]);
const filters = useSelector((state) => state.filter);
// not all consts is here, only to show the problem
const fetchData = async (token) => {
try {
const responseResult = await axios.get(
"http://apicall/example/all",
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
setDataResultsTotal(responseResult.data);
setAreaProgs(responseResult.data.length);
// and continuous some calc to send to updates the state and show to the user
});
setError(responseResult.data.erro);
} catch (error) {
console.error("something wrong", erro);
}
};
useEffect(() => {
setToken(localStorage.getItem("token"));
fetchData(token);
}, [token]);
const handleChangeSelect = (event) => {
setAvaliador(event.target.value);
dispatch(updateFilters({ ["name"]: event.target.value }));
};
const shouldDisplay = (lev) => {
let matchesSearchText = lev.noEncarregado
.toUpperCase()
.includes(filters.noEncarregado);
// let matchesCategory = lev.id.toLowerCase().includes(filters.ids);
// filters.ids.length > 0
// ? filters.ids.some((id) => id == lev.category)
// : true;
return matchesSearchText;
};
const filteredData = DataResultsTotal.filter((lev) => shouldDisplay(lev));
setDataResultsTotal(filteredData); // the error goes here
return (
<Box
paddingLeft={isOpen ? "80px" : "200px"}
bgcolor={`${colors.slate[100]}`}
>
<Grid container>
<Grid item xs={12} sm={6} md={6} lg={6}>
<Box>
<Typography
variant="h4"
sx={{
fontWeight: "bold",
marginLeft: "20px",
marginTop: "20px",
}}
>
text title
</Typography>
<Typography
variant="h6"
sx={{
marginLeft: "20px",
marginTop: "5px",
marginBottom: "20px",
}}
>
anotr text
</Typography>
</Box>
</Grid>
<Grid
item
xs={12}
sm={6}
md={6}
lg={6}
marginTop={"20px"}
marginBottom={"10px"}
>
<Box
display={"flex"}
alignItems={"center"}
height={"100%"}
justifyContent={"flex-end"}
>
<DownloadBtn DownText={true} />
</Box>
</Grid>
<Grid item xs={12} sm={6} md={3} lg={3}>
<Box sx={{ mx: "10px", my: "5px" }}>
<Box sx={{ minWidth: 150 }}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">
texttt
</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={avaliador}
label="Avaliador"
onChange={handleChangeSelect}
>
{avaliadoresList.map((avaliador) => (
<MenuItem key={avaliador} value={avaliador}>
{avaliador}
</MenuItem>
))}
</Select>
</FormControl>
</Box>
</Box>
</Grid>
<Grid item xs={6} sm={6} md={3} lg={3}>
<Box sx={{ mx: "10px", my: "5px" }}>
<CardHome
size="h7"
sizedesc="h3"
name="text"
icon={
<ListAltOutlinedIcon
sx={{
fontSize: "28px",
color: `${colors.greenAccent[800]}`,
}}
/>
}
description={<Counter from={0} to={showfiltereddata} />}
/>
</Box>
</Grid>
</Grid>
</Box>
);
}
Well, I’m trying to filter something with a select with Material-UI and Redux, everything is ok with the filter, but I’m not getting how I recalculated the filtered data and show to the user.
In this code, I will get the state from Redux, bring to the page, compare with the calculated data that’s becoming from API call, and save it on a const, but I need to recalculated this filtered data again, but when I try to do that, throws "too many re renders", and I know that why happens, but I don’t know the better approach to deal with it, maybe two useEffects
?
4
Answers
Do not keep the token in state.
You shouldn’t update state in an effect, especially if the state is a dependency of that effect.
this is causing this error to occur, i think what you should do is,
this is also not perfect solution but as i dont know your full use context i can only provide this as solution that might work!
To answer Codebling‘s question and your’s too I suppose, let’s analyze your code.
The behavior of the code above is that on initial render, the subroutine in the
useEffect
runs,setToken
then mutatestoken
andtoken
is a dependency of theuseEffect
so theuseEffect
will run again and again and… what you have created is an infinite loop.You have an unintentional side effect.
filteredData
is a new array reference each time the component renders, and each time a state update is enqueued and triggers a component rerender.Just compute and use directly the derived
filteredData
value, don’t use it to update the source of truth, e.g. thefilters
andDataResultsTotal
state. Remove the unintentional side-effectsetDataResultsTotal(filteredData);
from the code.Example:
or
Render the UI from the computed
filteredData
value instead of theDataResultsTotal
state now.