LotusFlower
LotusFlower

Reputation: 145

React hooks - useEffect method keeps fetching

In many of my components, I have to use token from store to get data and represent it (header menu, footer menu, products on page, slider images, etc.). What I am trying to do is to get this data only if I don't have it, but React keeps sending requests every time token changes (as token is dependency), even though I clearly put condition and I can see it if I console.log it. What am I doing wrong?

const [cities, setCities] = useState([]);

useEffect(() => {
 if (!cities.length) {
  fetch(`.....&token=${props.token}`)
  .then(response => response.json())
  .then(data => {

    if (data.data.results) {
    setCities(data.data.results.cities)

    }
   })
  }
}, [props.token, cities.length]);

Upvotes: 6

Views: 1226

Answers (2)

Renaldo Balaj
Renaldo Balaj

Reputation: 2440

// EDITED BECAUSE OF THE COMMENTS

// should be outside of the function
let timesExecuted = 0

function fetch () {
useEffect(() => {
if(props.token){
 timesExecuted = timesExecuted + 1
}

if (timesExecuted === 1) {
  fetch(`.....&token=${props.token}`)
  .then(response => response.json())
  .then(data => {

    if (data.data.results) {
    setCities(data.data.results.cities)
    }
   })
  }
}, [props.token]);
}

SO IT WILL COME every time BUT BE EXECUTED ONLY WHEN prop.token IS OKEY (feel free to modify the first IF based on token validations).

Upvotes: 0

Clarity
Clarity

Reputation: 10873

The cities will be empty on first render anyway, so you don't need to check for its length and specify it as a dependency:

const [cities, setCities] = useState([]);

useEffect(() => {
  fetch(`.....&token=${props.token}`)
    .then(response => response.json())
    .then(data => {
      if (data.data.results) {
        setCities(data.data.results.cities)
      }
    })
}, [props.token]);

You can also memoize the token to prevent it from triggering the useEffect callback:

const token = useMemo(() => props.token, []);

Upvotes: 2

Related Questions