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>
    );
}
相关推荐
Mh2 小时前
别再只会 `find` 了:Map 在前端业务里的真实用法
前端·javascript
陈随易2 小时前
FFmpeg 9.0 发布,代号 Lei,音视频处理再升级
前端·后端·程序员
爱丶狸3 小时前
Grafana_Zabbix_ImageRenderer_部署与前端操作手册
linux·前端·zabbix·grafana·kylin
用户059540174466 小时前
把AI对话记忆存储测试从手工改成Playwright+pytest,覆盖率从20%提到96%,回归时间缩短90%
前端·css
kyriewen6 小时前
别再这样写TypeScript了——Code Review中最常见的8个反模式
前端·javascript·typescript
名字还没想好☜6 小时前
Next.js ‘use client‘ 到底加在哪:Server/Client Components 边界与常见报错
开发语言·前端·javascript·react·next.js
午安~婉6 小时前
GitHub Token/ GitHub Stats统计显示图异常
前端·github·vercel·github token
码云之上7 小时前
AI Agent 工程化总览篇:从 Prompt 到 Harness
前端·人工智能
2501_926978337 小时前
以说明书 DNA 为模板——完整 AGI 的结构图景
前端·人工智能·经验分享·笔记·ai写作
IT_陈寒7 小时前
Vite静态资源引用这个坑我踩得有点疼
前端·人工智能·后端