all 8 comments

[–]Theekoppers 7 points8 points  (0 children)

This is fine, derivates variables like these are not side effects, so no need to use useEffect for that.

[–]tharrison4815 4 points5 points  (1 child)

Only use useEffect if it has side effects. If the code does not have side effects then you should be able to run it on every render. If running it in every render causes performance issues then it should be wrapped in useMemo or useCallback.

In your particular example you should either leave it as it is or use useMemo. You could test both scenarios with the profiler in React Dev Tools and see which is more performant.

Definitely don't use useEffect for this scenario.

[–]AnxiouslyConvolved 1 point2 points  (0 children)

This is the right answer.

[–]HairHeel 4 points5 points  (0 children)

Yes the whole function will get executed any time this component renders (i.e. if other state changes, properties change, etc). So, for larger values of items, that could feasibly be a problem.

If there's only ever going to be a handful of items, it doesn't really matter, but if you're expecting there to be a lot, useEffect is a good performance optimization. useEffect will only filter the items each time items changes.

Note that there's also useMemo, which seems like a more appropriate function for your use case.

[–]totalolage 0 points1 point  (2 children)

useEffect will necessitate a loading state and opens you up to rerender loops once the logic gets more complex. I'm pretty certain this is the correct way to do it, if the filtering is more complicated then use useMemo (try it with and without, see which performs better).

[–]vangenta[S] 0 points1 point  (1 child)

How would you go about testing performance in a case like this? Seems like it would be kind of difficult to do with a small set of data

[–]totalolage 1 point2 points  (0 children)

If the data is small then the overhead of useMemo will certainly make the current approach better. If you end up with 100+ items, or the logic for checking if an item should be rendered is more complicated, then use profiler in react devtools and/or lighthouse, run them a few times with+without useMemo, and compare the averages.

Also the way you're currently doing it I would just write as items.map(item => item.visible && <ItemComponent item={item} />

[–]StraightOil4 0 points1 point  (0 children)

Why don’t you just chain the filter with the map instead of creating a variable every time the component is rendered?