Я пытаюсь добавить закуску, чтобы отображать сообщение всякий раз, когда пользователь входит в систему или нет. Закусочная.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);
Когда я запускаю приложение, я получаю эту ошибку:
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)
Проблема связана с компонентом SnackBar. Я использую хуки useState, чтобы изменить состояние закусочной. Должен ли я использовать класс и componentShouldUpdate, чтобы не отображать несколько раз?
Можете ли вы проверить, вызывается ли handleClose несколько раз и решит ли проблема изменение handleClose = {handleClose} на handleClose = {()=>handleClose}?
@Nicholas Я пробовал, но получил ту же ошибку
у меня также была похожая проблема, но в моем случае это было связано с устаревшими значениями из предыдущих рендеров, я передал пустой массив зависимостей в useCallback и без необходимости обновлял состояние.
У меня была похожая ошибка, но это было из-за API, вызов которого дал сбой, и API автоматически удалился.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В SnackbarContentWrapper вам нужно изменить
<IconButton
key = "close"
aria-label = "Close"
color = "inherit"
className = {classes.close}
onClick = {onClose} // change this
>
к
<IconButton
key = "close"
aria-label = "Close"
color = "inherit"
className = {classes.close}
onClick = {() => onClose()} // to this
>
Так что он запускает действие только при нажатии.
Кроме того, вы можете просто вставить handleClose в SignInContainer, чтобы
const handleClose = () => (reason) => {
if (reason === 'clickaway') {
return;
}
setSnackBarState(false)
};
Это то же самое.
Спасибо, работает для меня. Это то, что я искал onClick = {() => onClose} .
Ага, ? спасибо; обновить мой вызов события с onClick = {onClose} на onClick = {() => onClose} Работал нормально.
спасибо на самом деле даже я забыл это, теперь я вспомнил.
может кто-нибудь сказать мне, что нужно гуглить, чтобы понять разницу между onClick = {() => onClose} и onClick = {onClose}? Спасибо!
Погуглив что-нибудь на тему «связывание встроенных функций в реакции», вы должны получить то, что вам нужно. вам придется узнать об этом в js и функциях каррирования, это довольно кроличья нора.
Именно то, что сработало для меня. Простой, но эффективный ответ. Весьма признателен.
Спасибо, это именно то, что я искал.
расскажите нам больше о технике карри
разница между onClick = {() => onClose} и onClick = {onClose}?
Я только учусь реагировать, и это сработало для меня!
Я подозреваю, что проблема заключается в том, что вы вызываете свой установщик состояния непосредственно внутри тела компонента функции, что заставляет React повторно вызывать вашу функцию снова с теми же реквизитами, что заканчивается повторным вызовом установщика состояния, который запускает Реагируйте, чтобы снова вызвать вашу функцию.... и так далее.
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>
)
}
Вместо этого я рекомендую вам просто условно установить значение по умолчанию для свойства состояния, используя тернарный код, чтобы в итоге вы получили:
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>
)
}
См. этот Демонстрация CodeSandbox.io для полной демонстрации того, как он работает, а также сломанный компонент, который у вас был, и вы можете переключаться между ними.
ваш ответ решает проблему, описанную в вопросе, однако переменная open всегда false
@ para008 Я добавил исчерпывающий демо, чтобы доказать, что он работает должным образом.
Я не нахожу свою ошибку, потому что openвсегда ложно для меня, однако !!вариант сначала ложен, а затем становится истинным
может быть, я должен задать это в другом вопросе. Спасибо за ответ.
@ para008 Посмотрите обновленную демонстрацию. Теперь он должен полностью работать и имитировать, когда variant не установлен.
Ваш ответ решил мою проблему, спасибо!
Вы должны связать событие в вашем onClick. Кроме того, функция click должна получать событие. См. пример
export default function Component(props) {
function clickEvent (event, variable){
console.info(variable);
}
return (
<div>
<IconButton
key = "close"
aria-label = "Close"
color = "inherit"
onClick = {e => clickEvent(e, 10)}
>
</div>
)
}
У меня тоже такая же проблема, и решение в том, что я не привязывал событие в своем onClick. поэтому, когда он отображается в первый раз и данных больше, что заканчивается повторным вызовом установщика состояния, что запускает React для повторного вызова вашей функции и так далее.
export default function Component(props) {
function clickEvent (event, variable){
console.info(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>
)
}
Вам нужно добавить событие, прежде чем вызывать функцию handleFunction следующим образом:
function SingInContainer() {
..
..
handleClose = () => {
}
return (
<SnackBar
open = {open}
handleClose = {() => handleClose}
variant = {variant}
message = {message}
/>
<SignInForm/>
)
}
Вы можете предотвратить эту ошибку, используя хуки внутри функции.
В моем случае причина в неправильном attribute имени onblur = {setFieldTouched('firstName')} -->onBlur = {()=>setFieldTouched('firstName')} . после исправления ошибки имени атрибута исчезла
Я думаю, вы можете это сделать. У меня дома работает без проблем.
const handleClose = (reason) => {
if (reason === 'clickaway') {
return;
}
setSnackBarState(false);
};
<SnackBar
open = {open}
handleClose = {()=>handleClose(r)}
variant = {variant}
message = {message}
/>
Из того, что я собрал, Похоже, ошибка возникает, когда мы вызываем так много функций.
mostly
setState()
Один из способов обойти это — установить состояния внутри функции, а не вызывать setState напрямую с помощью onClick, например.
Использование большого количества таких состояний, вероятно, приводит к повторному рендерингу реакции несколько раз, вызывая эту ошибку.
Вы, вероятно, используете Webpack, и в этом случае я хотел бы обратить ваше внимание на опцию инструмент разработчика, которая позволяет вам точно определить местонахождение ошибки в вашем исходном коде, вместо того, чтобы найти ошибку в вашем связанном коде, как у вас сейчас