Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop

后端 未结 5 561
小鲜肉
小鲜肉 2020-12-08 18:29

I\'m trying to add a snackBar in order to display a message whenever a user signIn or not. SnackBar.jsx:

import React from \"react\";
import PropTypes from \         


        
相关标签:
5条回答
  • 2020-12-08 18:48

    I suspect that the problem lies in the fact that you are calling your state setter immediately inside the function component body, which forces React to re-invoke your function again, with the same props, which ends up calling the state setter again, which triggers React to call your function again.... and so on.

    const SingInContainer = ({ message, variant}) => {
        const [open, setSnackBarState] = useState(false);
        const handleClose = (reason) => {
            if (reason === 'clickaway') {
              return;
            }
            setSnackBarState(false)
    
          };
    
        if (variant) {
            setSnackBarState(true); // HERE BE DRAGONS
        }
        return (
            <div>
            <SnackBar
                open={open}
                handleClose={handleClose}
                variant={variant}
                message={message}
                />
            <SignInForm/>
            </div>
        )
    }
    

    Instead, I recommend you just conditionally set the default value for the state property using a ternary, so you end up with:

    const SingInContainer = ({ message, variant}) => {
        const [open, setSnackBarState] = useState(variant ? true : false); 
                                      // or useState(!!variant); 
                                      // or useState(Boolean(variant));
        const handleClose = (reason) => {
            if (reason === 'clickaway') {
              return;
            }
            setSnackBarState(false)
    
          };
    
        return (
            <div>
            <SnackBar
                open={open}
                handleClose={handleClose}
                variant={variant}
                message={message}
                />
            <SignInForm/>
            </div>
        )
    }
    

    Comprehensive Demo

    See this CodeSandbox.io demo for a comprehensive demo of it working, plus the broken component you had, and you can toggle between the two.

    0 讨论(0)
  • 2020-12-08 19:05

    In SnackbarContentWrapper you need to change

    <IconButton
              key="close"
              aria-label="Close"
              color="inherit"
              className={classes.close}
              onClick={onClose}
            >
    

    to

    <IconButton
              key="close"
              aria-label="Close"
              color="inherit"
              className={classes.close}
              onClick={() => onClose}
            >
    
    

    so that it only fires the action when you click.

    Instead, you could just curry the handleClose in SingInContainer to

    const handleClose = () => (reason) => {
            if (reason === 'clickaway') {
              return;
            }
            setSnackBarState(false)
    
          };
    

    It's the same.

    0 讨论(0)
  • 2020-12-08 19:06

    You must link an event in your onClick. Additionally, the click function must receive the event. See the example

    export default function Component(props) {
    
        function clickEvent (event, variable){
            console.log(variable);
        }
    
        return (
            <div>
                <IconButton
                    key="close"
                    aria-label="Close"
                    color="inherit"
                    onClick={e => clickEvent(e, 10)}
                >
            </div>
        )
    }
    
    0 讨论(0)
  • 2020-12-08 19:06

    You need to add an event, before call your handleFunction like this:

    function SingInContainer() {
    ..
    ..
    handleClose = () => {
    }
    
    return (
        <SnackBar
            open={open}
            handleClose={() => handleClose}
            variant={variant}
            message={message}
            />
        <SignInForm/>
    )
    

    }

    0 讨论(0)
  • 2020-12-08 19:10

    I also have the same problem, and the solution is I didn't bind the event in my onClick. so when it renders for the first time and the data is more, which ends up calling the state setter again, which triggers React to call your function again and so on.

    export default function Component(props) {
    
    function clickEvent (event, variable){
        console.log(variable);
    }
    
    return (
        <div>
            <IconButton
                key="close"
                aria-label="Close"
                color="inherit"
                onClick={e => clickEvent(e, 10)} // or you can call like this:onClick={() => clickEvent(10)} 
            >
        </div>
    )
    }
    
    0 讨论(0)
提交回复
热议问题