Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

612
Vistas
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?

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

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.

over 4 years ago · Santiago Trujillo Denunciar

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.

over 4 years ago · Santiago Trujillo Denunciar

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> ) }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda