如何在React JS组件中避免setTimeout返回的ID被渲染显示
问题原因
你将setTimeout直接写在了JSX的{}内部,React会默认将花括号内表达式的返回值渲染到页面上,而setTimeout执行后会返回数字类型的定时器ID,因此出现了ID被展示的问题。此外setTimeout属于副作用逻辑,本身就不应该放在具备纯函数性质的render方法中执行。
解决方案
以下两种实现方式均可解决问题:
方案1:将定时器逻辑放到生命周期钩子中(类组件规范写法,推荐)
利用componentDidUpdate监听handleSubmit状态变化,状态切换为true时再启动定时器,同时在组件卸载时清理定时器避免内存泄漏。修改后的完整代码如下:
import "./form.css"; import React, { Component } from "react"; import GravityForm from "react-gravity-form"; import styled from "styled-components"; const SuccessMessage = styled.div` display: block; color: #fff; font-size: 24px; text-align: center; `; export class Gravity extends Component { state = { handleSubmit: false, } // 存储定时器ID,用于卸载时清理 timerId = null; componentDidUpdate(prevProps, prevState) { // 仅当handleSubmit从false变为true时触发定时器 if (!prevState.handleSubmit && this.state.handleSubmit) { this.timerId = setTimeout(() => { window.location.href = 'https://google.co.uk'; }, 3000); } } componentWillUnmount() { // 组件卸载时清理定时器,避免内存泄漏 if (this.timerId) clearTimeout(this.timerId); } render() { const { handleSubmit } = this.state; if (!handleSubmit) { return ( <GravityForm backendUrl="https://removedurlforclientprivacy.com/wp-json/glamrock/v1/gf/forms" formID="3" onSubmitSuccess={() => { this.setState({ handleSubmit: true, }) }} /> ); } else { return ( <> <SuccessMessage> <p>Thanks for entering our competition!<br />If you're our lucky winner, we will let you know.</p> </SuccessMessage> </> ) } } } export default Gravity
注:这里将styled组件移到了组件外部,是styled-components的推荐写法,避免重复渲染生成新的样式实例。
方案2:直接在提交成功回调中启动定时器
无需修改生命周期,直接在onSubmitSuccess的setState异步回调中启动定时器,确保状态更新、感谢消息渲染完成后再开始计时:
onSubmitSuccess={() => { this.setState({ handleSubmit: true }, () => { // setState第二个参数为状态更新后的回调,此时感谢消息已渲染到页面 setTimeout(() => { window.location.href = 'https://google.co.uk'; }, 3000) }) }}
你只需要将原来的onSubmitSuccess替换成上面的代码,再删掉render方法里的{ setTimeout(...) }即可生效。
内容的提问来源于stack exchange,提问作者Thomas Hewitt
相关产品推荐
相关产品推荐

