我有以下(简化)代码:
import React, { useState, useEffect } from "react";
import Button from '@material-ui/core/Button';
import Snackbar from '@material-ui/core/Snackbar';
import MuiAlert from '@material-ui/lab/Alert';
const CheckIn = props => {
const [success, setSuccess] = useState(false);
const [error, setError] = useState(false);
const handleClick = () => {
//send request to checkin :)
setSuccess(true);
}
return (
<>
<Button color="default" variant="contained" onClick={handleClick}>Check-in</Button>
<Alert open={success} severity="success">Succes</Alert>
<Alert open={error} severity="error">Error</Alert>
</>
)
}
const Alert = props => {
const [open, setOpen] = useState(props.open);
const handleClose = () => {
setOpen(false);
}
return (
<Snackbar open={open} autoHideDuration={6000} onClose={handleClose}>
<MuiAlert severity={props.severity} onClose={handleClose}>
{props.children}
</MuiAlert>
</Snackbar>
)
}
我的期望是,当从CheckIn组件中按下按钮时,success
变量将设置为true
并传递到Alert组件,这将打开Snackbar
并显示屏幕上的警报。之后的6秒钟,Snackbar
会触发handleClose
并再次关闭警报。
现在发生的是警报从不弹出。我尝试过的是将Snackbar open={open}
更改为Snackbar open={props.open}
,以检查是否从父级正确传递了属性,该方法可以正常工作,但此后将无法关闭警报。
我主要是在寻找为什么它不起作用的原因,而不是一种解决方法。
答案 0 :(得分:1)
当前在Alert中设置setOpen仅在Alert中设置本地状态,但在CheckIn中打开未更改。无需复制道具,您可以将功能从CheckIn传递给Alert来更改CheckIn中的打开值。
由于警报(及其关闭按钮)仅在打开状态为true时显示,因此您可以通过切换关闭警报。
const CheckIn = () => {
const [success, setSuccess] = React.useState(true);
const [error, setError] = React.useState(true);
const toggleSuccess = React.useCallback(
() => setSuccess(success => !success),
[]
);
const toggleError = React.useCallback(
() => setError(error => !error),
[]
);
return (
<React.Fragment>
<button onClick={toggleSuccess}>
toggle success
</button>
<button onClick={toggleError}>toggle error</button>
<div>
<Alert open={success} close={toggleSuccess}>
Succes
</Alert>
<Alert open={error} close={toggleError}>
Error
</Alert>
</div>
</React.Fragment>
);
};
const Alert = ({ open, close, children }) => {
return open ? (
<React.Fragment>
{children}
<div>
<button onClick={close}>close</button>
</div>
</React.Fragment>
) : (
''
);
};
ReactDOM.render(
<CheckIn />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>