Is there any way to call useeffect until the data had been fetched properly?

I want to fetch my data from backend mongodb but the useeffect is rendering only once and at that moment data is not fetched quickly resulting in lots of undefined errors. Here is my code:

const [xnaLogData,setXnaLogData]=useState([]);
const [xnaLogMember,setXnaLogMember]=useState("");
const [balance,setBalance]=useState(0);
 
useEffect(() => {
    setXnaLogMember(Cookies.get('member_userr'));
    alert(xnaLogMember);
    const calBal = () => {
        var sum = xnaLogData.reduce(function(prev, current) {
            return prev + +current.balance
        }, 0);
        setBalance(sum);
    }

    const fetchXna = async () => {
        const response = await fetch('/xnaloginforoute');
        const json = await response.json();
        setXnaLogData(json.xnacomp);
        calBal();
        console.log(json.xnacomp)
        console.log(xnaLogData);
    }

    fetchXna();
},[]);

If i put },[xnaLogData]); inside the useeffect line },[]); it will start a continous chain of useeffect and the data is fetching in 3rd or 4th attempt of effect. I am unable to solve this issue

Answer

Ok, this is a typical useEffect question.

Let’s revisit your logic a bit.

  useEffect(() => {
    setAbc(value)
  }, [abc])

The problem of the above is an endless loop, unless the value can reach a stable value after couple of runs. Thus most of time, we have a short circuit line installed to break it off.

  useEffect(() => {
    if (count > 2) return
    setCount(v => v + 1)
  }, [count])

Either way i think you get the idea, either loop or not, it’s entirely controlled by YOU, react is not going to make a decision what to do. You can rethink why you want to re-run the effect upon the value change.