Error rendered more hooks than during the previous render

I used to have a function component act as a page: export default function NormalList(props) { const pageSize = 20; const [page, setPage] = useState(1) const [searchString, setSearchSt...

So there are a couple of things you need to fix. First of all you should remove your function call from the useState function, you should only perform your side effects inside a useEffect hook see React Docs.

The next thing is whenever you decide to use the dependency array to your useEffect hook you should include all the dependencies of useEffect i.e all the props, state including functions inside your function component that you used inside your useEffect hook. So the Rule of Thumb is Never Lie About Your Dependencies! otherwise you will shoot yourself in the foot.

So the easiest option is to move your getCreditNoteList function inside your useEffect hook and add all the dependencies of your useEffect hook to the dependency array.


export default function NormalList({ customerId }) {
    const pageSize = 20;
    const [page, setPage] = useState(1)
    const [searchString, setSearchString] = useState(null);
    const [creditNotes, setCreditNotes] = useState({});
    const [ordering, setOrdering] = useState(null);

    useEffect(() => {

      function getCreditNoteList() {
        API.fetchCreditNoteList({
            account_id: customerId, 
            page, 
            page_size: pageSize, 
            searchString, 
            ordering
        }).then(data => {
            setCreditNotes(data);
        });
      }

      getCreditNoteList(),

       // add ALL! dependencies
    }, [page, searchString, ordering, pageSize, customerId]))

    return (
       <> </>
    )
}

Second Option
If you want to use the getCreditNoteList function elsewhere and want to keep it outside your useEffect hook you can do that by wrapping your getCreditNoteList logic inside the useCallback hook as shown below and add the function to your dependency array inside your useEffect hook for reasons i mentioned earlier.

export default function NormalList({ customerId }) {
    const pageSize = 20;
    const [page, setPage] = useState(1)
    const [searchString, setSearchString] = useState(null);
    const [creditNotes, setCreditNotes] = useState({});
    const [ordering, setOrdering] = useState(null);

    const getCreditNoteList = useCallback(() => {
        API.fetchCreditNoteList({
            account_id: customerId, 
            page, 
            page_size: pageSize, 
            searchString, 
            ordering
        }).then(data => {
            setCreditNotes(data);
        });
     // the function only changes when any of these dependencies change
    },[page, searchString, ordering, pageSize, customerId])

    useEffect(() => {

      getCreditNoteList(),

    },[getCreditNoteList])

    return (
       <> </>
    )
}

Содержание

  1. React Error: Rendered more hooks than during the previous render.
  2. My Solution!!
  3. useValue throws error — Rendered more hooks than during previous render #1126
  4. Comments
  5. Description
  6. Package versions
  7. React hooks report error: Rendered fewer hooks/Rendered more hooks
  8. Rendered more hooks than during the previous render

React Error: Rendered more hooks than during the previous render.

If you’ve ever written React with hooks, chances are, you’ve probably been greeted with this error at one time.

O ne of the things you might want to do when such error occurs is to ensure you are not violating any the rules from the Hooks documentation.

  • Call Hooks from React function components.
  • Call Hooks from custom Hooks
  • Don’t call Hooks from inside a function or a loop.

You might need to note that, there is a difference between

While both can return JSX, the later will be considered a React component and the former wouldn’t.

Well, all of that said. I recently encountered this error and off course the first thing I did was to check where this error was coming from. I was so sure I wasn’t violenting any of the aforementioned rules.

Well in my case I had these snippets where I needed to pass props around and was returning my component as a function.

For some reason, I know not of, returning my component in the form of a function, cause Hooks to be rendered more than necessary. In other to fix this, I had to read up blog posts. The sad thing was, none pointed at a solution that I sought. However, I found one that led me to finding a solution for myself.

My Solution!!

All I had to do at the end of the day was to replace my code with these lines.

Note the difference, I have replaced the function syntax with component syntax. This was the one solution to this problem I had. I hope it helps someone else who might encounter a similar error.

If you found this helpful, please give it some claps, or share so others can find it too.

Источник

useValue throws error — Rendered more hooks than during previous render #1126

Description

I am following this piece of document about how to use useValue in functional component because the dragging stops working after re-rendering in RN 0.62.2 app/react-native-reanimated 1.13/react-native-gesture-handler 1.7. Here is the code before change which runs fine:

Here is with useValue:

However the code above throws error:

Tried the following and the error is the same:

I can’t find more information about value except this one line statement in the document above. Tried useRef and useMemo and the error is the same. What is the right way in function component to reference a value? Code example appreciated!

The hook is declared in method :

Package versions

  • React: 16.11
  • React Native: 0.62.2
  • React Native Reanimated: 1.13.0

The text was updated successfully, but these errors were encountered:

I’m guessing you’re trying to call displayImg conditionally which breaks the method how React handles hooks. useValue is built on top of useRef , so this is problem with usage of hooks and not Reanimated.

Please provide full code defining and using useValue .
Closing until more info is given.

jakub-gonet , here is the code for function displayImg . Sorry it is long and a bit messy. I put a few lines for helping reading. Many thanks.

Here is how the displayImg gets called in switch :

You’re doing exactly this (conditional render of the hooks) in the line where you have case 1 : you’re calling displayImg as a function. In order to fix this, you should use it as a component —

After converting displayImg to function component, useValue is working.

In app, there are dragX, dragY, offsetX, offsetY, transX, transY, gesState, scale defined for gesture handling. Currently useValue only applied to dragX and dragY . What are the other variables which needs to be useValued for preserving state after re-rendering?

There is another use case which requires reset of all state and this is when uploading new images in DisplayImages which triggers re-rendering. User shall be able to drag and sort again after new images have been uploaded. Sorting only changes image order in data array and uploading increase the number of images in the data array.

By rule of thumb, you should reuse every Value with useValue() to prevent resetting state. Every other animated node should be reused as well, but that’s more like perf optimization, it doesn’t affect the correctness of the code.

Источник

React hooks report error: Rendered fewer hooks/Rendered more hooks

This is used during project development

Rendered more hooks than during the previous render

Before describing the actual situation of the project, let s take a look at one by one. Hell Local

Of course, I’m just giving an example, after all we use

Huh. cough. close to the subject, now we revise

Rendered more than last time

So let me take a look at how it is rendered more than the last time. First of all, the program rendering is

At this time due to

Then we modified the gender

But the program reported an error, and the final rendering result failed to be displayed normally. At this point, we found:

Indeed more than last time, more

What is going on here? Let’s take a look at the documents mentioned in the error message:

Only Call Hooks at the Top Level

Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls. (If you’re curious, we’ll explain this in depth below.)

Call only at the top

Do not call in loops, conditions or nested functions

Источник

When you are working with React Hooks, you may see the error: Uncaught Invariant Violation: Rendered more hooks than during the previous render. In this article, we will show you how to fix this article.

If we conditionally call a hook or return before all of the hooks have finished, we get the error “Rendered more hooks than during the last render”. Move all hooks to the top level of the function component and avoid using hooks within conditions to fix the problem.

Error

Uncaught Invariant Violation: Rendered more hooks than during the previous render.

Error - Uncaught Invariant Violation: Rendered more hooks than during the previous render - Clue Mediator

Error – Uncaught Invariant Violation: Rendered more hooks than during the previous render – Clue Mediator

Let’s take an example of how the error occurs and how to fix it.

Example 1

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import React, {useEffect, useState} from ‘react’;

function App() {

  const [counter, setCounter] = useState(0);

  // Error: Rendered more hooks than during the previous render.

  if (counter > 0) {

    // Calling React hook conditionally

    useEffect(() => {

      console.log(‘hello world’);

    });

  }

  return (

    <div>

      <button onClick={() => setCounter(counter + 1)}>toggle loading</button>

      <h1>Hello world</h1>

    </div>

  );

}

export default App;

Solution:

Because React hooks can only be invoked at the top level, we must relocate the condition within the hook to fix the issue.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import React, {useEffect, useState} from ‘react’;

function App() {

  const [counter, setCounter] = useState(0);

  // hook is called at top level (not conditionally)

  useEffect(() => {

    if (counter > 0) {

      console.log(‘hello world’);

    }

  });

  return (

    <div>

      <button onClick={() => setCounter(counter + 1)}>toggle loading</button>

      <h1>Hello world</h1>

    </div>

  );

}

export default App;

Example 2

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import React, {useState} from ‘react’;

function App() {

  const [counter, setCounter] = useState(0);

  // this returns before second hook runs if condition is met

  if (counter > 0) {

    return <h2>Returning early</h2>;

  }

  // Error because hook is called conditionally

  const [color, setColor] = useState(‘salmon’);

  return (

    <div>

      <button onClick={() => setCounter(counter + 1)}>toggle loading</button>

      <h1>Hello world</h1>

    </div>

  );

}

export default App;

Solution:

To fix the issue, we must shift all hooks to the component’s top level, above any circumstances that can result in a return value.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

import React, {useState} from ‘react’;

export default function App() {

  const [counter, setCounter] = useState(0);

  const [color, setColor] = useState(‘salmon’);

  // condition that may return early must be below all hooks

  if (counter > 0) {

    return <h2>Returning early</h2>;

  }

  return (

    <div>

      <button onClick={() => setCounter(counter + 1)}>toggle loading</button>

      <h1>Hello world</h1>

    </div>

  );

}

export default App;

Conclusion

  • Call hooks only at the top level.
  • Calling hooks inside of loops, conditions, or nested functions is not recommended.
  • Use hooks first, before any early returns, in the top level of your React method.
  • Only call hooks from React function components or from custom hooks.

I hope you find this article helpful.
Thank you for reading. Happy Coding..!! 🙂

If you found value in this article,
you can support us by buying me a coffee! ☕

I am trying to use useEffect in the if condition but I am facing the following error: Uncaught Invariant Violation: Rendered more hooks than during the previous render in Reactjs. In this Exerror article, We are going to learn about How to reproduce this error and we will discuss All Possible Solutions Let’s Get Started with This Article.

Contents

  1. How Uncaught Invariant Violation: Rendered more hooks than during the previous render Error Occurs?
  2. How To Solve Uncaught Invariant Violation: Rendered more hooks than during the previous render Error?
  3. Solution 1: Move Condition into useEffect
  4. Solution 2: React Hook Calling Rule
  5. Conclusion

I am trying to use useEffect in the if condition but I am facing the following error.

Uncaught Invariant Violation: Rendered more hooks than during the previous render

Here is my code

import {useState} from 'react';

export default function App() {
  const [votes, setVotes] = useState(0);

  if (votes > 0) {
    useEffect(() => {
      console.log('Up Vote Is Bigger Than 0');
    });
  }

  return (
    <div>
      <button onClick={setVotes(votes + 1)}>Vote Up</button>
      <h1>UpVotes: {votes}</h1>
    </div>
  );
}

So here I am writing all the possible solutions that I have tried to resolve this error.

How To Solve Uncaught Invariant Violation: Rendered more hooks than during the previous render Error?

  1. How To Solve Uncaught Invariant Violation: Rendered more hooks than during the previous render Error?

    To Solve Uncaught Invariant Violation: Rendered more hooks than during the previous render Error We Cannot run UseEffect Conditionally And that’s Why This error Occurs. You Just have to Move Your Condition into useEffect and then Your error will be resolved. Here in Above Code, I Was Using useEffect in the if Condition and that is Causing this error So I Just Moved my If Condition in the useEffect, and Then My Error was resolved.

  2. Uncaught Invariant Violation: Rendered more hooks than during the previous render

    To Solve Uncaught Invariant Violation: Rendered more hooks than during the previous render Error We Cannot run UseEffect Conditionally And that’s Why This error Occurs. You Just have to Move Your Condition into useEffect and then Your error will be resolved. Here in Above Code, I Was Using useEffect in the if Condition and that is Causing this error So I Just Moved my If Condition in the useEffect, and Then My Error was resolved.

Solution 1: Move Condition into useEffect

We Cannot run UseEffect Conditionally And that’s Why This error Occurs. You Just have to Move Your Condition into useEffect and then Your error will be resolved. Just like Below Code.

import {useState} from 'react';

export default function App() {
  const [votes, setVotes] = useState(0);

 useEffect(() => {
     if (votes > 0) {
         console.log('Up Vote Is Bigger Than 0');
     }
 });

  return (
    <div>
      <button onClick={setVotes(votes + 1)}>Vote Up</button>
      <h1>UpVotes: {votes}</h1>
    </div>
  );
}

Here in Above Code, I Was Using useEffect in the if Condition and that is Causing this error So I Just Moved my If Condition in the useEffect, and Then My Error was resolved.

Solution 2: React Hook Calling Rule

Here are some Rules for calling hooks.

  • Don’t call Hooks inside loops, conditions, or nested functions
  • Only Call Hooks from React Functions
  • Call Hooks from React function components.
  • Call Hooks from custom Hooks

Conclusion

It’s all About this error. I hope We Have solved Your error. Comment below Your thoughts and your queries. Also, Comment below which solution worked for you?

Also, Read

  • Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop
  • Failed to load config “react-app” to extend from
  • How to Set port in next.js
  • npm ERR! code ENOENT npm ERR! syscall open
  • How to update all dependencies in package.json to the latest version

jakub-gonet, here is the code for function displayImg. Sorry it is long and a bit messy. I put a few lines for helping reading. Many thanks.

  function displayImg (img_source, width, ht, index, modalWidth, modalHt, dataLen, sortFn) {
    const aniIndex= new Value(index);
    const aniGridPR = new Value(gridPerRow);
    const dragX = useRef(new Value(0)).current;  //<<==here is the code with useRef/useValue. Tried one line only. Same error for both
    const dragY = new Value(0);
    const offsetX = new Value(0);
    const offsetY = new Value(0);
    const state = new Value(-1);
    const scale = new Value(1);

    var gridPerRow;
    console.log("image width : ", width);
    console.log("image ht : ", ht);
    if (dataLen <= 4 && dataLen > 1) {
        gridPerRow = 2;
    } else if (dataLen > 4) {
        gridPerRow = 3;
    } else {
        gridPerRow = 1;
    };
    
    function onDrop ([x, y, indx, gridPR]) {
        var jump_y=0, jump_x=0, new_index, percentage;
        //jump_row               
        jump_y = y>0 ? Math.floor(y/ht) : -Math.floor(-y/ht);
        percentage = Math.abs((y%ht)/ht);
        //console.log("row percentage : ", percentage);
        if (percentage >= 0.3) (y>0 ? jump_y++ : jump_y--); //count if Y overlap 30% or more
        //jump col
        jump_x = x>0 ? Math.floor(x/width) : -Math.floor(-x/width);
        percentage = Math.abs((x%width)/width);
        if (percentage >= 0.3) (x>0 ? jump_x++ : jump_x--); //count if X overlap 30% or more
        new_index = indx + jump_y*gridPR + jump_x
        console.log("new index : ", new_index);
        if (new_index != indx) {
            sortFn(indx, new_index); //<<==sortFn is a method passed in from calling component to sort images after dragging.
        };
    };
    if (img_source && img_source!==[] && img_source!=={}) {
        if (dataLen == 1) { //<<==one image and no dragging but zooming.
            const scale = new Value(1);
            function onGestureStateChange() {
                //handle scaling. not yet implemented
            };
            let scaleStyle = {
                transform:[
                    { perspective: 500 },
                    {
                        scale :  scale
                    }
                ]
            };
            return (
                <><PinchGestureHandler onHandlerStateChange={onGestureStateChange}>  //<<==allow to zoom in image 
                    <Animated.View style={scaleStyle}>
                    <GridImage
                        img_source={img_source}
                        width={width}
                        ht={ht}
                        index={index}
                        modalWidth={modalWidth}
                        modalHt={modalHt}
                    />
                    
                    <ModalImage
                        img_source={img_source}
                        modalWidth={modalWidth}
                        modalHt={modalHt}
                        index={index}
                    />
                    </Animated.View>
                    </PinchGestureHandler>
                </>
                );
        } else {  //<<==when multiple images presented
            console.log("ani code");
            
            const addX = add(offsetX, dragX);
            const addY = add(offsetY, dragY);
            const transX = cond(eq(state, State.ACTIVE), addX);  
            const transY = cond(eq(state, State.ACTIVE), addY, 
                                    cond(eq(state, State.END), 
                                        cond(or(greaterOrEq(abs(divide(dragX,new Value(width))), new Value(0.3)), greaterOrEq(abs(divide(dragY,new Value(ht))), new Value(0.3))), 
                                            call([addX, addY, aniIndex, aniGridPR], onDrop))
                                        )  //<<==when image is moved 30% or more on X or Y, then call method onDrop. otherwise no move (image back to its original position)
                                    );
                                    
            const handleGesture = event([
                {
                  nativeEvent: {
                    translationX: dragX,
                    translationY: dragY,
                    state,
                  },
                }, 
              ]);
            
            let aniStyle = {
                transform:[
                    { translateX : transX },
                    { translateY : transY },
                    
                ]
            };
            let scaleStyle = {
                transform:[
                    { perspective: 500 },
                    {
                        scale :  scale
                    }
                ]
            };
            return (
                <>
        
                    <PanGestureHandler 
                        onGestureEvent={handleGesture} 
                        onHandlerStateChange={handleGesture}
                        minPointers={1}
                        maxPointers={1}>
                        <Animated.View style={[aniStyle ]}>
                        <GridImage
                            img_source={img_source}
                            width={width}
                            ht={ht}
                            index={index}
                        />
                        </Animated.View>
                    </PanGestureHandler>
            
               
                <ModalImage  
                    img_source={img_source}
                    modalWidth={modalWidth}
                    modalHt={modalHt}
                    index={index}
            />  //<<==show full image in modal
                
                </>
                );
        };
        
    } else {
        return null;
    };
    
};    

Here is how the displayImg gets called in switch:

  switch(len) {  //len is the number of images in array
    case 0:
        return;
    case 1:
        
        return (
            <>
                {displayImg(picPath(pics[0]), screen_width*full, screen_width*full, 0, screen_width, pics[0].height*(screen_width/pics[0].width), len)}                   
            </>
            );
    case 2:  //<<==2-4 image will be displayed in 2 rows
        /* console.log("pics before return : ", pics);
        return (                   
            <Grid style={{position:"absolute", paddingTop:0,paddingLeft:0}}>
                <Row style={styles.row}>   
                    {pics.map((item, index) => {
                        return (displayImg(picPath(item), screen_width*half, screen_width*half, index,  screen_width, item.height*(screen_width/item.width), len, move))
                    })}                 
                </Row>
            </Grid>
        ); */
    case 3: 
    case 4:
        return (
            <Grid style={{position:"absolute", paddingTop:0,paddingLeft:0}}>
                {pics.map((item, index) => {
                    if (index%2===0) {  
                        if (pics[index+1]) {
                            return (
                                <Row style={styles.row}>
                                    {displayImg(picPath(item), screen_width*half, screen_width*half, index,  screen_width, item.height*(screen_width/item.width), len, move)}
                                    {displayImg(picPath(pics[index+1]), screen_width*half, screen_width*half, index+1,  screen_width, pics[index+1].height*(screen_width/pics[index+1].width), len, move)}
                                </Row>    
                            )} else {
                            return (
                                <Row style={styles.row}>
                                    {displayImg(picPath(item), screen_width*half, screen_width*half, index,  screen_width, item.height*(screen_width/item.width), len, move)}
                                </Row>    
                            )};                                           
                    }
                })}                        
            </Grid>
        );

    default:  //<<==more than 4 images will be displayed in 3 rows with 3 columns
        return (
            <Grid style={{position:"absolute", paddingTop:0,paddingLeft:0}}>
                {pics.map((item, index) => {
                    if (index%3===0) {  
                        if (pics[index+2]) {
                            return (
                                <Row style={styles.row}>
                                    {displayImg(picPath(item), screen_width*oneThird, screen_width*oneThird, index,  screen_width, item.height*(screen_width/item.width), len, move)}
                                    {displayImg(picPath(pics[index+1]), screen_width*oneThird, screen_width*oneThird, index+1,  screen_width, pics[index+1].height*(screen_width/pics[index+1].width), len, move)}
                                    {displayImg(picPath(pics[index+2]), screen_width*oneThird, screen_width*oneThird, index+2,  screen_width, pics[index+2].height*(screen_width/pics[index+2].width), len, move)}
                                </Row>    
                        )} else if (pics[index+1]) {
                            return (
                                <Row style={styles.row}>
                                    {displayImg(picPath(item), screen_width*oneThird, screen_width*oneThird, index,  screen_width, item.height*(screen_width/item.width), len, move)}
                                    {displayImg(picPath(pics[index+1]), screen_width*oneThird, screen_width*oneThird, index+1,  screen_width, pics[index+1].height*(screen_width/pics[index+1].width), len, move)}
                                </Row>    
                        )} else if (!pics[index+1]) {
                            return (
                                <Row style={styles.row}>
                                    {displayImg(picPath(item), screen_width*oneThird, screen_width*oneThird, index,  screen_width, item.height*(screen_width/item.width), len, move)}
                                </Row>
                        )} else {
                            return null;
                        };                                           
                    }
                })}                        
            </Grid>
        );

    };        

Понравилась статья? Поделить с друзьями:
  • Error removing file permission denied
  • Error remote upstream already exists
  • Error remote unpack failed unable to create temporary object directory
  • Error remote target already exists
  • Error remote origin already exists что это