1

I have the following piece of code

const IssuesItems: React.FC<IProps> = function ({ issuesProp }) {
  const [issues] = useState<any>([...issuesProp]);
  const [paginatedIssues, setPaginatedIssues] = useState<any>([]);
  const [currentPage, setCurrentPage] = useState<any>(1);
  const [itemsPerPage, setItemsPerPage] = useState<any>(13);
  const [numberOfPages, setNumberOfPages] = useState<any>(null);

  useEffect(() => {
    // set the number of pages
    const numberOfPages = Math.ceil(issues.length / itemsPerPage);
    console.log(numberOfPages);
    setNumberOfPages(numberOfPages);
  }, []);

  useEffect(() => {
    console.log(numberOfPages);
    const newArr = splitArray(issues, numberOfPages);
    console.log('new arr');
    console.log(newArr);
  }, [numberOfPages]);

Problem is that, the second useEffect, is triggered on load, when numberOfPages is null, shouldn't it be triggered only after setNumberOfPages is triggered for the first time?

I can fix it doing this

 useEffect(() => {
    if (numberOfPages != null) {
      const newArr = splitArray(issues, numberOfPages);
      console.log('new arr');
      console.log(newArr);
    }
  }, [numberOfPages]);

But should it only be fired after the numberOfPages state is modified by a setNumberOfPages call?

mouchin777
  • 1,428
  • 1
  • 31
  • 59
  • adding a reference in second array means, run the effect after componentDidMount and any changes on the second item ! I think the best solution is adding a `if` to check `null` – Mohammad Esmaeilzadeh Nov 21 '21 at 13:32

2 Answers2

3

By default, useEffect always runs after the first render.

The dependency array in useEffect lets you specify the conditions to trigger it. If you provide useEffect an empty dependency array, it’ll run exactly once.

If you want to trigger only after setNumberOfPages is triggered for the first time then the way you're using it is right:

useEffect(() => {
    if (numberOfPages != null) {
      const newArr = splitArray(issues, numberOfPages);
      console.log('new arr');
      console.log(newArr);
    }
  }, [numberOfPages]);

Additionally, you can check out this awesome StackOverflow answer: https://stackoverflow.com/a/59841947/16420018

And this article by Dan Abramov: https://overreacted.io/a-complete-guide-to-useeffect/

Sanket Shah
  • 2,888
  • 1
  • 11
  • 22
1

the useEffect you have (2nd) would be run on the initial render, and then every subsequent render where numberOfPages changes its value.

Problem is that, the second useEffect, is triggered on load, when numberOfPages is null, shouldn't it be triggered only after setNumberOfPages is triggered for the first time?

you cannot escape the initial render. but conditionally you can make it do nothing as you did. useRef is also used to escape the effect of initial render.

emre-ozgun
  • 676
  • 1
  • 7
  • 17