即使卸载后组件也会保留状态
我正在与Formik建立反馈表,并希望从类组件过渡到钩子,但要面对上述困难。
function Feedback(props) {
const [fileInfo, setFileInfo] = useState("");
const [feedbackStatus, setFeedbackStatus] = useState("");
let timer = null;
useEffect(() => {
const status = props.feedbackResponse.status;
if (status) {
if (status >= 200 && status < 300) {
setFeedbackStatus("success");
timer = setTimeout(() => {
props.history.goBack();
}, 2500);
} else if (status === "pending") {
setFeedbackStatus("pending");
} else {
setFeedbackStatus("error");
}
}
return () => {
clearInterval(timer);
}
}, [props.feedbackResponse.status]);
// ...code ommited for brevity
}
在我提交表单之后,等待服务器响应后,此效果成功运行。 Feedback
组件是react-router
模态组件,如果需要的话。但是,如果我重新打开该模式,则会看到成功消息,而不是新表格。在return
中,我有条件地呈现一条成功消息,如果feedbackStatus === "success"
或根据服务器响应可能以其他方式显示错误消息的形式。我的班级组件可以在以下代码中正常工作:
componentDidUpdate(prevProps) {
const status = this.props.feedbackResponse.status;
if (prevProps.feedbackResponse.status !== status) {
if (status >= 200 && status < 300) {
this.setState({feedbackStatus: "success"});
this.timer = setTimeout(() => {
this.props.history.goBack();
}, 2500);
} else if (status === "pending") {
this.setState({feedbackStatus: "pending"});
} else {
this.setState({feedbackStatus: "error"});
};
}
}
componentWillUnmount() {
clearInterval(this.timer);
}
预期的输出:成功提交表单后,重新打开此模式组件应呈现新表单,但呈现先前的提交状态。这使我认为我根本没有卸载Feedback
组件,但是我的错误在哪里?
答案 0 :(得分:2)
发生上述行为是因为效果也同时在初始渲染上运行,在这种情况下,props.feedbackStatus
可能会保留在先前的实例中。
由于只希望在组件更新时执行效果,因此您将需要停止在初始渲染时执行useEffect ,即使将值传递到依赖项数组时也会发生这种情况。您可以使用useRef
function Feedback(props) {
const [fileInfo, setFileInfo] = useState("");
const [feedbackStatus, setFeedbackStatus] = useState("");
const isInitialRender = useRef(true);
let timer = null;
useEffect(() => {
if(isInitialRender.current === true) {
isInitialRender.current = false;
} else {
const status = props.feedbackResponse.status;
if (status) {
if (status >= 200 && status < 300) {
setFeedbackStatus("success");
timer = setTimeout(() => {
props.history.goBack();
}, 2500);
} else if (status === "pending") {
setFeedbackStatus("pending");
} else {
setFeedbackStatus("error");
}
}
}
return () => {
clearInterval(timer);
}
}, [props.feedbackResponse.status]);
}
答案 1 :(得分:1)
您可以使用<Feedback key={someKey} />
。
这将确保您在重新打开它时创建一个新的“反馈”组件实例,从而从状态中清除旧的成功/失败消息。