为什么说不要滥用setState

本文探讨了React中setState的使用对组件性能的影响,强调了合理使用setState以减少不必要的渲染次数的重要性。通过实例对比,展示了如何将多个状态更新合并为一次setState调用,以及如何正确使用setState的函数形式来确保状态更新的准确性。

setState 成本比较高,每setState一次都会调用render渲染一次,setState会影响性能
如下面调用了四个setState,那么会render四次

import React,{ Component } from 'react';
class index extends Component {
    constructor(props) {
        //构造函数
        super(props);
        this.state = { 
            date: new Date(),
            count01:0,
            count02:10,
            count03:100,
         }
         console.log("contructor-->",props)    
    };
     tick=()=>{
        console.log("tick->called")
        this.setState({
            date: new Date()
        })
        this.setState({
            count01:this.state.count01++
        })
        this.setState({
            count02:this.state.count02++
        })
        this.setState({
            count03:this.state.count03++
        })
    }
    componentDidMount(){
        console.log("DidMount")
        this.timer = setInterval(() =>{
            this.tick()
        },1000)
    }
        render() {
        console.log("render-->",this.state)
        const {date} = this.state;
        return (
        <h2>现在是:{date.toLocaleTimeString()}</h2>
        );
    }
}
export default index;

因为上面设置了定时器,每秒会执行一次tick(),红框中是执行一次tick()打印出来的
在这里插入图片描述
所以,为了提高组件性能,尽量一次把所有要改变的值放到同一个setState里面

import React,{ Component } from 'react';
class index extends Component {
    constructor(props) {
        //构造函数
        super(props);
        this.state = { 
            date: new Date(),
            count01:0,
            count02:10,
            count03:100,
         }
         console.log("contructor-->",props)    
    };
     tick=()=>{
        console.log("tick->called")
         this.setState({
            date: new Date(),
            count01:this.state.count01++,
            count02:this.state.count02++,
            count03:this.state.count03++
        })
    }
    componentDidMount(){
        console.log("DidMount")
        this.timer = setInterval(() =>{
            this.tick()
        },1000)
    }
        render() {
        console.log("render-->",this.state)
        const {date} = this.state;
        return (
        <h2>现在是:{date.toLocaleTimeString()}</h2>
        );
    }
}
export default index;

在这里插入图片描述
这里需要注意的是,this.props 和this.state可能是一部更新的,不应该依靠它们的值来计算下一个状态。
例如上面的 count01:this.state.count01++,可能无法更新,要修复它,要使用第二种形态的setState()来接收一个函数而不是一个对象,该函数将接收先前的状态作为第一个参数(pre),将此次更新被应用时的props作为第二个参数(参数名可以自己设置)

this.setState((pre,props)=>({
            date: new Date(),
            count01:pre.count01 +1,
            count02:pre.count02 +1,
            count03:pre.count03 +1
        }))

原本是写成

this.setState((pre,props)=>({
            date: new Date(),
            count01:pre.count01 ++,
            count02:pre.count02 ++,
            count03:pre.count03 ++
        }))

因为++是先赋值再加,等于没变,所以 ++ 无效,所以换成了+1
另外要避免直接将props中的属性赋值给state中的属性

this.state = {
	name = this.props.name //尽量避免使用这种方法,props改变时name 不会更新
}
import 'package:flutter/material.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../../services/supabase_service.dart'; class ResetPasswordPage extends StatefulWidget { const ResetPasswordPage({super.key}); @override _ResetPasswordPageState createState() => _ResetPasswordPageState(); } class _ResetPasswordPageState extends State<ResetPasswordPage> { final _emailController = TextEditingController(); bool _isLoading = false; Future<void> _resetPassword() async { setState(() => _isLoading = true); try { await SupabaseService.resetPassword(_emailController.text.trim()); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('重置邮件已发送')), ); if (mounted) Navigator.pop(context); } on AuthException catch (error) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(error.message)), ); } finally { setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('重置密码')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _emailController, decoration: const InputDecoration(labelText: '注册邮箱'), keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 20), ElevatedButton( onPressed: _isLoading ? null : _resetPassword, child: _isLoading ? const CircularProgressIndicator() : const Text('发送重置邮件'), ), ], ), ), ); } } flutter,密码重置页面无法发送邮件密码重置,写一个新的密码重置页实现功能
11-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值