Home > Mobile >  why useSelector() with conditions EslintError
why useSelector() with conditions EslintError

Time:11-11

Why this would be a violation of the hooks rules.?

In my case:

const getTopicId = useSelector((state) => state.topics.selectTopic.topicId) !== "" ? useSelector((state) => state.topics.selectTopic.topicId) : JSON.parse(localStorage.getItem("topic")).topicId;

I don't put a condition inside the useSelector, i try to say that if useSelector() has data, use it, if not use the localStorage data.

the solution that accept EsLint is: Put the useSelector inside a variable and then inside the ternary....but i don't understant why.

const getTopicSelector = useSelector((state) => state.topics.selectTopic.topicId);

 const getTopicId = useSelector((state) => state.topics.selectTopic.topicId) !== "" ? getTopicSelector : JSON.parse(localStorage.getItem("topic")).topicId

Thanks for your explanations.

CodePudding user response:

Your code sometimes calls useSelector once and sometimes twice.

If you take

const getTopicId = useSelector((state) => state.topics.selectTopic.topicId) !== "" ? useSelector((state) => state.topics.selectTopic.topicId) : JSON.parse(localStorage.getItem("topic")).topicId;

and rewrite the ternary to if..else, you can see that clearly:

let getTopicId;
const conditionTopicId = useSelector((state) => state.topics.selectTopic.topicId)
if (conditionTopicId !== "") {
  getTopicId = useSelector((state) => state.topics.selectTopic.topicId)
} else {
  getTopicId = JSON.parse(localStorage.getItem("topic")).topicId
};

Sometimes you call a hook once, sometimes twice. This violates the rules of hooks and will make React crash in the long run.

In your case, you can rewrite that quite simple:

let getTopicId = useSelector((state) => state.topics.selectTopic.topicId)
if (getTopicId == "") {
  getTopicId = JSON.parse(localStorage.getItem("topic")).topicId
}

And suddenly you call the hook only once - and you don't do it conditionally.

You can also go with a ternary and put the logic inside one hook call:

const getTopicId = useSelector(
  (state) => 
    state.topics.selectTopic.topicId !== "" ? 
      state.topics.selectTopic.topicId :  
      JSON.parse(localStorage.getItem("topic")).topicId
  )

All of these alternatives are fine - the only important thing: don't call useSelector inside a condition (and a ternary is just a short way of writing if...else).
React does not allow for that and it will crash on you sooner or later if you do.

CodePudding user response:

useSelector return a certain type which is not compatible with whatever the values sending from the localstorage

Best way to handle this condition is to add a separate useMemo variable

const {selectTopic} = useSelector((state) => state.topics)

const getTopicId  = useMemo(() => {
   return  selectTopic.topicId !== "" ? getTopicSelector : JSON.parse(localStorage.getItem("topic")).topic
}, [selectTopic])
  • Related