React hook called conditionally

In this blog post I have covered ways to work around classic error associated with react hooks.
"React Hook useSomeHook is called conditionally. React Hooks must be called in the exact same order in every component render."


Case 1 To solve this error one can simply move the useHook code above all the coditions.

Code with error
if (someCondition) {
 const data = useFetchDataNew();
 //some more code here ...
 //some more code here ...
 //some more code here ...
}
Solution
Now here simple fix is going to move the useSomeHook code above out of condition.
Correct code will look like
const data = useFetchDataNew();
if (someCondition) {
 //some more code here ...
 //some more code here ...
 //some more code here ...
}

Case 2 In some cases it is not possible to move code at the top of component as it has some dependency on the user input or something else. For example we have following code of useFetchData.
This hook need someId to fetch the data.

const [someId, setSomeId] = useState<string>("");
if (someId) {
  const data = useFetchDataNew(someId);
  data.then((res) => console.log(res));
}
const useFetchData = async (someId: string) => { 
 const response = await fetch(`${API}someId`); 
 const data = await response.json(); 
 return data; 
 }; 
}

Now in this case if we cannot have someId available then we cannot call `useFetchData`. To solve this problem we can have multiple solutions.


Solution 1

If you access to the useFechData hook then we can return a function instead of data from the hook. So that we can call the function to fetch data when have someId ready.

const useFetchData = async () => { 
 function fetchData(someId: string) {
  const response = await fetch(`${API}someId`); 
  const data = await response.json(); 
  return data; 
  }; 
 }
 return { fetchData };
}

Solution 2

Suppose you do not have to the useFetchData hook then we can have a hack with components. In this case we can create 2 diffrent components

1. When we donot have someId
2. When we have someId And then we call them conditionally.
Code will look like as follows
if (someCondition) {
 <ComponentWhereSomeIdIsNotReady />
 } else {
 <ComponentWhereSomeIdIsReady />
 }
}

By doing this we can have useFetchData hook inside ComponentWhereSomeIdIsReady

ComponentWhereSomeIdIsNotReady we can call when someId is ready and where we can show loading state or something.


Considering both solutions, I think solution 1 is better and suits in most of condition.