概述
React的状态管理
1.class组件
在传统的class组件中,react的状态管理大多依赖以下三种方式:
- props
- state
- context
下面来简单说一下以上三种方式
1.props
子组件一般通过父组件传递的props
值来进行相应的展示,自身没有自己的状态。这也造成了一些问题,只有父元素主动触发了props
的修改,受控组件的的渲染才会进行相应的改变,这样的应用场景显然太单薄了,受控组件当然也有需求通过自身的一些变化能够触发自身的重新渲染,最常见的例子input
受控组件输入框,如何做到输入框的值来自于父组件的props
,而当输入框输入内容时又能够更改输入框中显示的值呢?这就要说一说react
的设计思路了,基于jsx
语法的能够直接书写js
代码的组件式开发框架,在react
中可以直接灵活的书写js
代码,这就有了让js
的高阶函数发挥作用的机会了,通过函数的传递,将父组件中更改数据的函数传入子组件中,子组件触发相应的操作时调用该函数,并传入相应的值,就能够做到更改父组件中的数据,这也是函数式编程的优势之一,灵活且强大的抽象能力。这种高阶函数传递的方式也是常说的react
子组件向父组件传递值的方式。
在react
中数据是单向流动的,数据只能从父组件到子组件,而通过高阶函数的方式则能够实现将子组件的值传入父组件中。这对于经常使用js
的人来说是相当熟悉且友好的
2.state
子组件一般不接收props
,自身内部维护自己的state
。组件的重新渲染一般通过调用自己的setState
方法进行,这里说一个老生长谈的问题:react
的setState
方法到底是同步的还是异步的?答案是两种都有,在不同的情况下会有不同的处理方法,总的来说如果是在react
的可控范围内调用该方法,那么该方法就是异步的,这样做的好处是能够批量汇总setState
的调用值,进行state
的一次性更新,能够减少内部重新渲染的次数,有助于提高性能,由于这个原因,在react
的生命周期函数中调用的该方法的的话,此时直接读取state
的值是没有更改的,针对这个问题,react
也提供了相应的解决办法,setState
方法可以跟一个函数,这个函数接收一个参数,这个参数就是当前state
的变化汇总,由于是react
自己实现的,因此这样并不会导致重新渲染却能够获取正确的state
值,而不在react
的可控范围内调用该方法的话就只能是同步的,原因也很好理解,因为当前的调用状态react
已经不可控了,没法进行异步汇总更新。那么什么情况是可控的什么又是不可控呢,简单来说在reatc
的生命周期内触发的话就是可控的,因为调用过程由react
控制,而不在生命周期内触发比如在setTimeout中触发就不可控,因为当前调用setState
的是浏览器的行为,检测的话也比较简单,只需要判断一下当前函数中的this
就行了。
3.context嵌套传值
典型的生产者消费者模式,用以解决react
中祖先组件向子孙组件传递状态时每一层都需要写props
的问题,这既不清晰也不优雅。当然这也造成了新的问题,组件树的嵌套会进一步加深,给人的感觉就像回调地域
2.hook函数
class
组件存在一些小问题,比如class
语法会有一定的复杂度、class
组件的生命周期函数都只有一份这就导致了一个组件有太多的副作用操作时需要将逻辑全部写在该生命周期函数中,虽然可以进行方法抽取,但抽取出来函数一般也是与该组件耦合性较深的,因为该函数一般需要当前组件的内部状态作为副作用的参数,或者直接需要该组件的dom
对象,此外副作用函数与清除副作用的函数不能在视觉上写在一起,造成了后续维护的麻烦,并且由于js
的特性,函数中的this
指向问题也比较绕,基于种种原因,react
在16版本中推出了hook
函数,让以前存在感不是很足的函数组件也能够实现class
组件的生命周期函数功能,在实际体验上做到基本一致。
说一说我知道的hook
函数实现原理,由于函数组件不会使用new
来创建react
组件对象,那么react
的hook
函数如何实现为特定函数组件服务,并且在特定时期调用特定的方法呢?首先,hook
函数是react
自己实现的api
,这就有很大的操作空间了,react
会在内部使用一个栈,用来记录当前被调用的函数组件,如果在函数组件中使用了hook
函数,那么react
就可以通过当前栈顶函数知道被服务的组件,接着在组件的不同的生命周期触发不同的hook
函数体就行了,这也是函数组件重新渲染后会重新执行的原因,函数在栈中执行完成会出栈,下次需要再将组件树重新执行一次就又能够重新入栈,继续hook
函数的执行。
由于有了直接获取服务组件的概念,就不再需要像class
组件中那样在组件树书写时就确定context
的嵌套关系,可以在子组件需要时使用useContext
的hook
函数来直接获取祖先组件的提供值,并且可以通过多次调用获取多个。各个生命周期hook
函数的功能也更加灵活,可以书写多个,副作用函数与取消副作用函数也可以直接写在一起。
当然基于栈以及重新渲染就重新执行的概念,hook
函数也造成了自己的问题,那就是js
的陈旧闭包,js
中的函数会生成自己的作用域,每一次的函数组件重新执行时里面的变量就重新生成并处于一个新的作用域中,如果里面写的所有hook
函数也重新生成执行,这显然是不合适的,但如果不重新执行hook
函数本身作用域中的变量就可能是过时失效的了,所以hook
函数被设计成了通过依赖来决定是否重新生成的机制。
redux的作用
1.redux的作用
基于react
的context
机制实现的统一状态管理的工具,将原本在各个组件中分散的状态进行统一管理。redux
的操作一般是在当前组件中获取一部分的state
状态,当前组件执行了操作后dispatch
一个新的action
更改任务,redux
的reducer
获取到更改任务对state
进行相应的更改,受到该state
更改影响的组件重新渲染。
2.redux的简单实现
// 使用context实现store
import React, { useContext, createContext } from "react";
// 实现store对象
class Store {
constructor(reducer, init) {
// reducer函数,处理不同的派发请求
this.reducer = reducer;
// state, store对象存储的数据
this.state = init;
// 派发任务执行时的监听器
this.listeners = [];
}
// 获取store对象存储的数据
getState = () => {
return this.state;
};
// 派发任务的函数
dispatch = (action) => {
this.state = this.reducer(this.state, action);
this.listeners.forEach((it) => {
it();
});
};
// 添加额外触发器的函数,每一次dispath后都会执行的函数
subscribe = (listener) => {
this.listeners.push(listener);
// 返回一个取消监听的函数
return () =>
(this.listeners = this.listeners.filter((it) => it != listener));
};
}
// 实现redux的createStore方法
function createStore(reducer, init) {
return new Store(reducer, init);
}
// 创建一个provider
let StoreContext = createContext();
// 实现react-redux的Provider组件, 用法<Provider store={store}></Provider>
function Provider({ store, children }) {
return (
<StoreContext.Provider value={store}>{children}</StoreContext.Provider>
);
}
// 实现react-redux的useSelector() hook函数, 从store存储的数据中提取数据
function useSelector(selector) {
let store = useContext(StoreContext);
return selector(store.getState());
}
// 实现react-redux的useDispath() hook函数, 使用store对象派发操作
function useDispatch() {
let store = useContext(StoreContext);
return function (action) {
store.dispatch(action);
};
}
// 实现react-redux的useStore()
hook函数, 直接获取store对象
function useStore() {
return useContext(StoreContext);
}
最后
以上就是无私小馒头为你收集整理的react的状态管理以及reduxReact的状态管理的全部内容,希望文章能够帮你解决react的状态管理以及reduxReact的状态管理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复