【从零开始学 React | 第九章】Class类组件zustand

张开发
2026/4/16 3:33:24 15 分钟阅读

分享文章

【从零开始学 React | 第九章】Class类组件zustand
前言本章主要讲解了React Class 类组件的基础写法、生命周期、组件通信以及Zustand 状态管理库的基础使用、异步操作和模块化切片模式。【从零开始学 React | 第九章】Class类组件zustand一Class类组件1.基础结构2.生命周期函数3.组件通信二zustand1.基础结构2.异步支持3.切片模式一Class类组件概念Class 类组件是使用 ES6 类class语法定义的、有自己独立状态state和生命周期的 React 组件。1.基础结构类组件就是通过 JS 中的类来组织组件的代码:classCounterextendsComponent{// 定义状态变量state{count:0}// 事件回调clickHandler(){this.setState({count:this.state.count1})}// UI模板(JSX)render(){returnbutton onClick{this.clickHandler}{this.state.count}/button}}1.通过类属性state定义状态数据2.通过setState方法来修改状态数据3.通过render来写 UI 模版JSX 语法一致hook和它的区别1.写法更简单类组件class render () thisHook 组件普通函数 return不用写 this2.状态管理不同类组件this.state this.setState()Hook 组件useState() 直接定义、修改3.代码量更少同样功能Hook 代码少 30%~50%4.使用场景类组件老项目、旧代码Hook 组件现在官方推荐、新项目全用这个2.生命周期函数概念组件从创建到销毁的各个阶段自动执行的函数就是生命周期函数案例// Class API 生命周期import{Component,useState}fromreactclassSonextendsComponent{// 声明周期函数// 组件渲染完毕执行一次 发送网络请求componentDidMount(){console.log(组件渲染完毕了请求发送起来)// 开启定时器this.timersetInterval((){console.log(定时器运行中)},1000)}// 组件卸载的时候自动执行 副作用清理的工作 清除定时器 清除事件绑定componentWillUnmount(){console.log(组件son被卸载了)// 清除定时器clearInterval(this.timer)}render(){returndivi am Son/div}}functionApp(){const[show,setShow]useState(true)return({showSon/}button onClick{()setShow(false)}unmount/button/)}exportdefaultApp3.组件通信概念类组件和 Hooks 编写的组件在组件通信的思想上完全一致三种通信方式父传子通过 prop 绑定数据子传父通过 prop 绑定父组件中的函数子组件调用兄弟通信状态提升通过父组件做桥接案例// Class APIimport{Component}fromreactclassCounterextendsComponent{// 编写组件的逻辑代码// 1. 状态变量 2. 事件回调 3.UI(JSX)// 1. 定义状态变量state{count:0}// 2. 定义事件回调修改状态数据setCount(){// 修改状态数据this.setState({count:this.state.count1})}render(){returnbutton onClick{this.setCount}{this.state.count}/button}}functionApp(){return(Counter//)}exportdefaultApp1.父传子 直接通过prop子组件标签身上绑定父组件中的数据即可2.子传父 在子组件标签身上绑定父组件中的函数子组件中调用这个函数传递参数总结1.思想保持一致2.类组件依赖于this二zustand概念Zustand 是一个轻量、简单、无 Provider 的 React 状态管理库用于跨组件共享数据比 Redux 更简洁易用。官网zustand1.基础结构语法import{create}fromzustandconstuseStorecreate((set)({// 同步数据count:0,// 同步方法直接 set 修改状态addCount:(){set({count:10})},// 基于旧值修改increment:(){set((state)({count:state.count1}))}}))1.函数参数必须返回一个对象 对象内部编写状态数据和方法2.set是用来修改数据的专门方法必须调用它来修改数据语法1参数是函数 需要用到老数据的场景语法2参数直接是一个对象 set({ count: 100 })案例// zustandimport{create}fromzustand//1. 创建storeconstuseStorecreate((set){return{// 状态数据count:0,// 修改状态数据的方法inc:(){set((state)({count:state.count1}))}}})// 2. 绑定store到组件// useStore { count, inc }functionApp(){const{count,inc}useStore()return(button onClick{inc}{count}/button/)}exportdefaultApp2.异步支持对于异步的支持不需要特殊的操作直接在函数中编写异步逻辑最后只需要调用 set 方法传入新状态即可语法constuseStorecreate((set)({list:[],getList:async(){const{data}awaitaxios.get(/api/xxx)set({list:data})}}))案例// zustandimport{useEffect}fromreactimport{create}fromzustandconstURL...// 1. 创建storeconstuseStorecreate((set){return{// 状态数据count:0,// 修改状态数据的方法inc:(){set((state)({count:state.count1}))},channelList:[],fetchGetList:async(){constresawaitfetch(URL)constjsonResawaitres.json()set({channelList:jsonRes.data.channels})}}})// 2. 绑定store到组件// useStore { count, inc }functionApp(){const{count,inc,fetchGetList,channelList}useStore()useEffect((){fetchGetList()},[fetchGetList])return(button onClick{inc}{count}/buttonul{channelList.map(itemli key{item.id}{item.name}/li)}/ul/)}exportdefaultApp3.切片模式场景当单个 store 比较大的时候可以采用 切片模式 进行模块拆分组合类似于模块化语法1.步骤 1定义独立切片countStore /channelStore// 切片1countStore计数器相关状态与方法constcountSlice(set)({count:0,increment:()set((state)({count:state.count1})),reset:()set({count:0})})// 切片2channelStore频道列表相关状态与异步方法constchannelSlice(set)({channelList:[],loading:false,fetchChannels:async(){set({loading:true})const{data}awaitaxios.get(/api/channels)set({channelList:data.channels,loading:false})}})2.步骤 2合并切片创建根 storerootStoreimport{create}fromzustand// 合并所有切片生成根storeconstuseRootStorecreate((...a)({...countSlice(...a),...channelSlice(...a)}))exportdefaultuseRootStore步骤 3组件中使用根 storefunctionComponent(){// 从根store中按需取状态和方法const{count,increment,channelList,fetchChannels}useRootStore()return(divp计数{count}/pbutton onClick{increment}1/buttonbutton onClick{fetchChannels}加载频道/buttonul{channelList.map(cli key{c.id}{c.name}/li)}/ul/div)}最后如果我的内容对你有帮助请点赞评论收藏创作不易。大家的支持就是我坚持下去的动力

更多文章