Redux是一个用于JavaScript应用的状态管理库,广泛应用于React应用中。
Redux的缺点
Redux是内存中的状态存储,每次状态更新都会返回新的状态对象,这可能会导致内存的过度使用。其内存占用高,性能差。因此更加不适合在 React Native 中使用。
Redux采用全局状态管理,但更多时侯,我们可能只需要一个用于组件间通信的消息中间件,dispatch 触发的状态,并不需要集中存储。使用Redux可能会显得繁重和冗余。
Redux的状态集中存储比较有利于状态的存储和恢复。比如如果Redux用localStorage持久化,这样用户刷新页面时,单页应用还可以恢复刷新之前的状态。但这种场景对于React native应用来说并不常用,而且状态持久化也可以手动来实现。
我们可以通过 PubSubJS 使用类似消息中间件(发布、订阅)的方法来管理组件间的通信和数据的传递,其本身并不存储状态和处理状态变化,极大的提高性能和简化开发流程,大概如下:
登陆组件->登陆->publish 登陆成功事件
父组件->subscribe登陆成功事件->切换到欢迎界面
欢迎界面->subscribe登陆成功事件->用登陆返回的token获取图片列表
使用这种方式的好处是,兄弟组件间通信不必再像使用props那种通过父组件来通信,多层组件之间通信也不必在一层一层的传递, 直接在触发事件的组件中发布消息 监听组件中订阅消息即可;
组件安装
添加消息中间件
yarn add pubsub-js
项目中如果用的typescript,添加类型声明文件,为IDE提供智能提示
yarn add -D @types/pubsub-js
消息发布
pubsub 的消息发布非常简单一行 publish 即可。比如这里有一个 Login 组件。当登陆成功后,要通知上级界面和欢迎界面切换视图。这里定义了事件类型 EventType。
import { publish } from 'pubsub-js';
export const EventType = {
USER_SIGNIN: 'USER.SIGNIN',
USER_SIGNUP: 'USER.SIGNUP',
}
type LoginParams = {
style?: StyleProp<ViewStyle>;
}
const LoginPage = (params: LoginParams) => {
const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState('');
const handleLogin = async() => {
const isSuccess = await Login({ username, password })
if (isSuccess) {
console.log('event publish')
publish(EventType.USER_SIGNIN, isSuccess)
}
};
消息订阅
消息的接受也非常简单,subscribe 即可。这里使用 useEffect 防止组件的重复渲染,造成事件的多次接收。
import { subscribe } from 'pubsub-js';
export enum PAGE_VIEW {
HOMEPAGE,
IMAGE_PLAYER,
VIDEO_PLAYER,
LOGINPAGE,
WELCOMEPAGE,
}
let prevViewBeforeVideoOrImage = PAGE_VIEW.HOMEPAGE
let currentImageOrVideoIndex = 0
function App(): React.JSX.Element {
const [ pageView, setPageView ] = useState(PAGE_VIEW.WELCOMEPAGE)
useEffect(() => {
subscribe(EventType.USER_SIGNIN, (message, isSuccess: boolean) => {
console.log('recevied user logined', message, isSuccess)
setPageView(PAGE_VIEW.HOMEPAGE)
})
}, [])
可见,PubSubJS 的使用非常简洁。
相关阅读: 使用PubSub-JS时ReactNative在后台运行一段时间唤醒后,组件无法scribe到publish的事件,typescript实现一个事件订阅发布组件