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>
    );
}
相关推荐
梦想的颜色4 分钟前
前端UI宝藏SKILL——UI/UX Pro Max
前端·ui·ux
無名路人20 分钟前
uniApp 小程序 vue3 app.vue静默登录其他页面等待登录完成方式二
前端·微信小程序·ai编程
CoCo的编程之路25 分钟前
2026 前端效能飞跃:深度解析智能助手的页面构建最大化方案
前端·人工智能·ai编程·智能编程助手·文心快码baiducomate
Dxy123931021631 分钟前
Python 去除 HTML 标签获取纯文本
开发语言·python·html
砚底藏山河1 小时前
python、JavaScript 、JAVA,定制化数据服务,助力业务高效落地
java·javascript·python
JavaAgent架构师1 小时前
前端AI工程化(一):AI通信协议深度解析
前端·人工智能
11_x1 小时前
JS 底层:乖宝宝引擎和乖宝宝声明
javascript
flex罗小黑1 小时前
前端手机号脱敏的 4 个层级,你在第几层?
javascript
林恒smileZAZ1 小时前
前端如何让图片、视频、pdf等文件在浏览器直接下载而非预览
前端·pdf
孙6903421 小时前
electron播放本地任意格式的视频
前端·javascript