• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
    • Questions
    • Teachers
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

509
Views
Violación invariable no detectada: Demasiadas re-renderizaciones. React limita el número de renderizados para evitar un bucle infinito

Estoy tratando de agregar un snackBar para mostrar un mensaje cada vez que un usuario inicia sesión o no. SnackBar.jsx:

 import React from "react"; import PropTypes from "prop-types"; import classNames from "classnames"; import CheckCircleIcon from "@material-ui/icons/CheckCircle"; import ErrorIcon from "@material-ui/icons/Error"; import CloseIcon from "@material-ui/icons/Close"; import green from "@material-ui/core/colors/green"; import IconButton from "@material-ui/core/IconButton"; import Snackbar from "@material-ui/core/Snackbar"; import SnackbarContent from "@material-ui/core/SnackbarContent"; import { withStyles } from "@material-ui/core/styles"; const variantIcon = { success: CheckCircleIcon, error: ErrorIcon }; const styles1 = theme => ({ success: { backgroundColor: green[600] }, error: { backgroundColor: theme.palette.error.dark }, icon: { fontSize: 20 }, iconVariant: { opacity: 0.9, marginRight: theme.spacing.unit }, message: { display: "flex", alignItems: "center" } }); function SnackbarContentWrapper(props) { const { classes, className, message, onClose, variant, ...other } = props; const Icon = variantIcon[variant]; return ( <SnackbarContent className={classNames(classes[variant], className)} aria-describedby="client-snackbar" message={( <span className={classes.message}> <Icon className={classNames(classes.icon, classes.iconVariant)} /> {message} </span> )} action={[ <IconButton key="close" aria-label="Close" color="inherit" className={classes.close} onClick={onClose} > <CloseIcon className={classes.icon} /> </IconButton> ]} {...other} /> ); } SnackbarContentWrapper.propTypes = { classes: PropTypes.shape({ success: PropTypes.string, error: PropTypes.string, icon: PropTypes.string, iconVariant: PropTypes.string, message: PropTypes.string, }).isRequired, className: PropTypes.string.isRequired, message: PropTypes.node.isRequired, onClose: PropTypes.func.isRequired, variant: PropTypes.oneOf(["success", "error"]).isRequired }; const MySnackbarContentWrapper = withStyles(styles1)(SnackbarContentWrapper); const CustomizedSnackbar = ({ open, handleClose, variant, message }) => { return ( <div> <Snackbar anchorOrigin={{ vertical: "bottom", horizontal: "left" }} open={open} autoHideDuration={6000} onClose={handleClose} > <MySnackbarContentWrapper onClose={handleClose} variant={variant} message={message} /> </Snackbar> </div> ); }; CustomizedSnackbar.propTypes = { open: PropTypes.bool.isRequired, handleClose: PropTypes.func.isRequired, variant: PropTypes.string.isRequired, message: PropTypes.string.isRequired }; export default CustomizedSnackbar;

SignInFormContainer.jsx:

 import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import SnackBar from '../../components/SnackBar'; import SignInForm from './SignInForm'; const SingInContainer = ({ message, variant}) => { const [open, setSnackBarState] = useState(false); const handleClose = (reason) => { if (reason === 'clickaway') { return; } setSnackBarState(false) }; if (variant) { setSnackBarState(true); } return ( <div> <SnackBar open={open} handleClose={handleClose} variant={variant} message={message} /> <SignInForm/> </div> ) } SingInContainer.propTypes = { variant: PropTypes.string.isRequired, message: PropTypes.string.isRequired } const mapStateToProps = (state) => { const {variant, message } = state.snackBar; return { variant, message } } export default connect(mapStateToProps)(SingInContainer);

Cuando ejecuto la aplicación me sale este error:

 Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop. at invariant (http://localhost:9000/bundle.js:34484:15) at dispatchAction (http://localhost:9000/bundle.js:47879:44) at SingInContainer (http://localhost:9000/bundle.js:79135:5) at renderWithHooks (http://localhost:9000/bundle.js:47343:18) at updateFunctionComponent (http://localhost:9000/bundle.js:49010:20) at beginWork (http://localhost:9000/bundle.js:50020:16) at performUnitOfWork (http://localhost:9000/bundle.js:53695:12) at workLoop (http://localhost:9000/bundle.js:53735:24) at HTMLUnknownElement.callCallback (http://localhost:9000/bundle.js:34578:14) at Object.invokeGuardedCallbackDev (http://localhost:9000/bundle.js:34628:16)

El problema se debe al componente SnackBar. Uso los ganchos useState para cambiar el estado de snackBar. ¿Debo usar una clase y un componentShouldUpdate para no renderizar varias veces?

about 3 years ago · Santiago Trujillo
3 answers
Answer question

0

Sospecho que el problema radica en el hecho de que está llamando a su setter de estado inmediatamente dentro del cuerpo del componente de la función, lo que obliga a React a volver a invocar su función nuevamente, con los mismos accesorios, lo que termina llamando al setter de estado nuevamente, lo que desencadena Reacciona para volver a llamar a tu función... y así sucesivamente.

 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> ) }

En su lugar, te recomiendo que simplemente establezcas condicionalmente el valor predeterminado para la propiedad estatal usando un ternario, para que termines con:

 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> ) }

Demostración completa

Vea esta demostración de CodeSandbox.io para obtener una demostración completa de su funcionamiento, además del componente roto que tenía, y puede alternar entre los dos.

about 3 years ago · Santiago Trujillo Report

0

En SnackbarContentWrapper necesitas cambiar

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

para

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

Para que solo dispare la acción cuando haga clic.

Alternativamente, podría cursar el identificador SignInContainer handleClose

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

Es lo mismo.

about 3 years ago · Santiago Trujillo Report

0

Debe vincular un evento en su onClick. Además, la función de clic debe recibir el evento. Ver el ejemplo

 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> ) }
about 3 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error