[英]Default value in useState not getting re-initialised
I have a snack bar component
, which displays a toast message for a few seconds and then disappears.我有一个
snack bar component
,它会显示一条吐司消息几秒钟然后消失。 I have an App component
which contains a button
, and on click of that button
, I want to control the snack bar component
.我有一个
App component
,其中包含一个button
,单击该button
,我想控制snack bar component
。 On the first click, the snack bar
appears fine and disappears after the time specified is over.在第一次单击时,
snack bar
显示正常,并在指定的时间结束后消失。 But when I click it again, the snack bar
doesn't appear.但是当我再次单击它时,
snack bar
不会出现。 I am initializing the show state
to true every time, still, the snack bar
isn't appearing.我每次都将
show state
初始化为 true,但仍然没有出现snack bar
。 Please tell me where I am going wrong and how to rectify this.请告诉我哪里出错了以及如何纠正。 Below are the files.
下面是文件。 I am using a custom hook to control the behavior of snack bar's appearance.
我正在使用自定义钩子来控制小吃店外观的行为。
App.js应用程序.js
import React, { useState } from "react";
import { Snackbar } from "./Snackbar";
function App() {
const [display, setDisplay] = useState(false);
return (
<div>
<button onClick={() => setDisplay(true)}>Click me</button>
{display && <Snackbar message="hello" />}
</div>
);
}
export default App;
Snackbar.js Snackbar.js
import React from "react";
import { useSnackbar } from "./useSnackbar";
const Snackbar = ({ message }) => {
const { showSnackbar } = useSnackbar();
return (
showSnackbar && (
<div>
<p>{message}</p>
</div>
)
);
};
export { Snackbar };
useSnackbar.js使用Snackbar.js
import { useState, useEffect } from 'react';
const useSnackbar = () => {
const [showSnackbar, setSnackbar] = useState(true);
const [snackbarMessage, setSnackbarMessage] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
setSnackbar(false);
setSnackbarMessage('');
}, 3000);
return () => {
clearTimeout(timer);
};
}, [showSnackbar]);
return {
showSnackbar,
setSnackbar,
snackbarMessage,
setSnackbarMessage
};
};
export { useSnackbar };
It's true that the useSnackbar
hook has a default value of true
for showSnackbar
and it does get changed to false
after 3 seconds but display
in App.js
stays true
which means that even after the timeout
.该这是真的
useSnackbar
钩有一个默认值true
为showSnackbar
和它得到改变为false
后3秒,但display
在App.js
保持true
这意味着即使后timeout
。
Since display
never gets set to false
, Snackbar
never gets unmounted so the state of useSnackbar
never gets reinitialized.由于
display
永远不会被设置为false
, Snackbar
永远不会被卸载,所以useSnackbar
的状态永远不会被重新初始化。
My suggestion would be to change the structure of how useSnackbar
is being used.我的建议是改变
useSnackbar
的使用结构。
I'd move useSnackbar
into App.js
and set the snackbar open states there.我将
useSnackbar
移动到App.js
并在那里设置小吃店打开状态。
function App() {
const { showSnackbar, setSnackbar } = useSnackbar();
return (
<div>
<button onClick={() => setSnackbar(true)}>Click me</button>
{showSnackbar && <Snackbar message="hello" />}
</div>
);
}
const useSnackbar = () => {
const [showSnackbar, setSnackbar] = useState(false);
// rest of code
};
const Snackbar = ({ message }) => (
<div>
<p>{message}</p>
</div>
);
There are other ways to structure thee components but for your example, this would be one of the simplest solutions.还有其他方法可以构建这些组件,但对于您的示例,这将是最简单的解决方案之一。
You don't reset your display
state in App.js您不会在 App.js 中重置您的
display
状态
Pass a reset state callback function to Snackbar
to pass to the useSnackbar
hook.将重置状态回调函数传递给
Snackbar
以传递给useSnackbar
钩子。
const useSnackbar = (onClose) => { // <-- callback function
const [showSnackbar, setSnackbar] = useState(true);
const [snackbarMessage, setSnackbarMessage] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
setSnackbar(false);
setSnackbarMessage('');
onClose && onClose(); // <-- invoke when timer expired
}, 3000);
return () => {
clearTimeout(timer);
onClose && onClose(); // <-- edge case if component unmounts before expire
};
}, [onClose, showSnackbar]);
return {
showSnackbar,
setSnackbar,
snackbarMessage,
setSnackbarMessage
};
};
const Snackbar = ({ message, onClose }) => {
const { showSnackbar } = useSnackbar(onClose); // <-- pass callback to hook
return (
showSnackbar && (
<div>
<p>{message}</p>
</div>
)
);
};
export default function App() {
const [display, setDisplay] = useState(false);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div>
<button onClick={() => setDisplay(true)}>Click me</button>
{display && <Snackbar message="hello" onClose={() => setDisplay(false)} />} // <-- pass reset callback
</div>
</div>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.