React - 类组件 setState 的 2 种写法、LazyLoad、useState

一、类组件 setState 的 2 种写法

1、对象式 setState
js 复制代码
setState(stateChange, [callback])
  1. stateChange 为状态改变对象,该对象可以体现出状态的更改

  2. callback 是可选的回调函数,它在状态更新完毕、界面也更新后(render 函数调用后)才被调用

js 复制代码
this.setState({
    count: this.state.count + 1,
});
js 复制代码
this.setState(
    {
        count: this.state.count + 1,
    },
    () => {
        console.log("更新后的 count:", this.state.count);
    },
);
2、函数式 setState
js 复制代码
setState(updater, [callback])
  1. updater 为返回 stateChange 对象的函数,updater 可以接收到 prevState 和 props 参数

  2. callback 是可选的回调函数,它在状态更新完毕、界面也更新后(render 函数调用后)才被调用

js 复制代码
this.setState((prevState, props) => ({
    count: prevState.count + 1,
}));
js 复制代码
this.setState(
    (prevState, props) => ({
        count: prevState.count + 1,
    }),
    () => {
        console.log("更新后的 count:", this.state.count);
    },
);
3、注意事项
  1. 如果新状态不依赖于原状态,使用对象式 setState;如果新状态依赖于原状态,使用函数式 setState
jsx 复制代码
// 最终 count 为 1,两次都基于旧的 this.state.count 计算

import { Component } from "react";

export default class App extends Component {
    state = {
        count: 0,
    };

    add = () => {
        this.setState({
            count: this.state.count + 1,
        });
        this.setState({
            count: this.state.count + 1,
        });
    };

    render() {
        return (
            <div>
                <h3>{this.state.count}</h3>
                <button onClick={this.add}>Add</button>
            </div>
        );
    }
}
jsx 复制代码
// 最终 count 为 2,每次都基于上次的 this.state.count 计算

import { Component } from "react";

export default class App extends Component {
    state = {
        count: 0,
    };

    add = () => {
        this.setState((prevState, props) => ({
            count: prevState.count + 1,
        }));
        this.setState((prevState, props) => ({
            count: prevState.count + 1,
        }));
    };

    render() {
        return (
            <div>
                <h3>{this.state.count}</h3>
                <button onClick={this.add}>Add</button>
            </div>
        );
    }
}
  1. 如果需要在 setState 执行后获取最新的状态数据, 要在 callback 中读取
jsx 复制代码
this.setState({
    count: this.state.count + 1,
});
console.log(this.state.count);

// 输出结果为 0
jsx 复制代码
add = () => {
    this.setState((prevState, props) => ({
        count: prevState.count + 1,
    }));
    console.log(this.state.count);

    // 输出结果为 0
};

二、LazyLoad

1、基本介绍
  1. 通过 lazy 函数配合 import 函数动态加载路由组件,路由组件代码会被分开打包

  2. 通过 <Suspense> 指定,在加载得到路由打包文件前,显示一个自定义加载界面

2、演示
(1)page
  1. About 页面
jsx 复制代码
import { Component } from "react";

export default class About extends Component {
    render() {
        return <h2>About</h2>;
    }
}
  1. Home 页面
jsx 复制代码
import { Component } from "react";

export default class Home extends Component {
    render() {
        return <h2>Home</h2>;
    }
}
  1. Loading 页面
jsx 复制代码
import { Component } from "react";

export default class Loading extends Component {
    render() {
        return (
            <div>
                <h1 style={{ backgroundColor: "gray", color: "orange" }}>Loading...</h1>
            </div>
        );
    }
}
(2)main
  1. App 组件
jsx 复制代码
import { Component, lazy, Suspense } from "react";
import { NavLink, Route } from "react-router-dom";
import Loading from "./pages/Loading";
import "./App.css";

const Home = lazy(() => import("./pages/Home"));
const About = lazy(() => import("./pages/About"));

export default class App extends Component {
    render() {
        return (
            <div>
                <div>
                    <NavLink to="/about">About</NavLink>
                    <NavLink to="/home">Home</NavLink>
                </div>
                <div>
                    <Suspense fallback={<Loading />}>
                        <Route path="/about" component={About} />
                        <Route path="/home" component={Home} />
                    </Suspense>
                </div>
            </div>
        );
    }
}
css 复制代码
.active {
    color: red;
}
  1. index.js
js 复制代码
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";

ReactDOM.render(
    <BrowserRouter>
        <App />
    </BrowserRouter>,
    document.getElementById("root"),
);
3、打包影响
  1. 使用 LazyLoad 后的打包
  1. 不使用 LazyLoad 后的打包

三、useState

1、基本介绍
  • useState 让函数式组件也可以有 state,并进行 state 数据的读写操作
js 复制代码
const [xxx, setXxx] = useState(initValue)
  1. initValue:第一次初始化指定的值在内部作缓存

  2. [xxx, setXxx]:包含 2 个元素的数组,第 1 个为内部当前状态值,第 2 个为更新状态值的函数

  • setXxx 的 2 种写法
  1. setXxx(newValue):参数为非函数值,直接指定新的状态值,内部用其覆盖原来的状态值

  2. setXxx(value => newValue):参数为函数,接收原本的状态值,返回新的状态值,内部用其覆盖原来的状态值

2、基本使用
jsx 复制代码
import { useState } from "react";

export default function App() {
    const [count, setCount] = useState(0);

    const add = () => {
        setCount(count + 1);
    };

    return (
        <div>
            <h3>{count}</h3>
            <button onClick={add}>Add</button>
        </div>
    );
}
3、注意事项
  • 如果新状态不依赖于原状态,setXxx 使用参数为非函数值;如果新状态依赖于原状态,setXxx 使用参数为函数
jsx 复制代码
// 最终 count 为 1,两次都基于旧的 count 计算

import { useState } from "react";

export default function App() {
    const [count, setCount] = useState(0);

    const add = () => {
        setCount(count + 1);
        setCount(count + 1);
    };

    return (
        <div>
            <h3>{count}</h3>
            <button onClick={add}>Add</button>
        </div>
    );
}
jsx 复制代码
// 最终 count 为 2,每次都基于上次的 count 计算

import { useState } from "react";

export default function App() {
    const [count, setCount] = useState(0);

    const add = () => {
        setCount((prevCount) => prevCount + 1);
        setCount((prevCount) => prevCount + 1);
    };

    return (
        <div>
            <h3>{count}</h3>
            <button onClick={add}>Add</button>
        </div>
    );
}
相关推荐
聊聊MES那点事2 小时前
JavaScript图表控件AG Charts使用教程:使用AG Charts React实时更新柱状图
开发语言·javascript·react.js·图表控件
自由生长20243 小时前
IndexedDB的观察
前端
IT_陈寒4 小时前
Vite热更新坑了我三天,原来配置要这么写
前端·人工智能·后端
斯班奇的好朋友阿法法4 小时前
离线ollama导入Qwen3.5-9B.Q8_0.gguf模型
开发语言·前端·javascript
掘金一周4 小时前
每月固定续订,但是token根本不够用,掘友们有无算力焦虑啊 | 沸点周刊 4.2
前端·aigc·openai
小村儿4 小时前
连载加餐01-claude code 源码泄漏 ---一起吃透 Claude Code,告别 AI coding 迷茫
前端·后端·ai编程
莫物4 小时前
vue过滤表格数据导致的索引错乱问题
前端·javascript·vue.js
竹林8184 小时前
从监听失败到实时更新:我在NFT铸造项目中搞定合约事件监听的全过程
前端·javascript
光影少年4 小时前
手写防抖和节流
前端·javascript·前端框架