Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Native 强大却不起眼的AppRegistry #10

Open
1uokun opened this issue Aug 17, 2021 · 0 comments
Open

React Native 强大却不起眼的AppRegistry #10

1uokun opened this issue Aug 17, 2021 · 0 comments
Labels
blog 日常开发笔记

Comments

@1uokun
Copy link
Member

1uokun commented Aug 17, 2021

在构建React Native项目中,我们常常使用官方提供的脚手架react-native-cli ,优点是能快速启动一个强大完整的RN项目,缺点就是失去了自己搭建脚手架带来的那份快乐,也常常会忽略掉一些脚手架内核心API。今天我将介绍一个不起眼却强大的API - AppRegistry

React Native AppRegistry

AppRegistry表示所有React Native应用的JS入口,运行一个RN项目大致会进行下述操作,AppRegistry.registerComponent注册根组件, AppRegistry.runApplication运行代码包。

查看方法

  • registerComponent
  • setWrapperComponentProvider
  • registerHeadlessTask/startHeadlessTask

registerComponent()

1.注册App根组件(react-native-cli根组件App.js),常用于单入口项目

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json'; //唯一的入口名称

AppRegistry.registerComponent(appName, () => App);
  1. 也可以多入口,原生端也需要注册多个不同的getMainComponentNameReactActivity用于跳转
AppRegistry.registerComponent("appName1", () => App1);
AppRegistry.registerComponent("appName2", () => App2);
  1. 获取原生端传递过来的参数
    原生端交互教程:https://github.com/React-Sextant/react-native-bridge-docs/wiki/ReactActivity#string-getmaincomponentname

4.动态插入组件到根组件[1]
由于registerComponent()是一个全局静态方法,所以我们可以在已经注册过入口的组件内任意地方调用该方法,只要保持appKey一致性,就能随时改变根组件,但我们一般不会一下就把整个根组件替换,常用于在根组件基础上动态插入一些全局组件,以方法调用的形式控制隐藏和显示。比如我们可以非原生地实现使用Toast.show()方法显示自定义Toast组件。

具体实现 https://gist.github.com/1uokun/1553994ef18ff6d51026c4a93e4c15ae

//将已被注册过的赋予变量名,防止重复注册报错
const originRegister = AppRegistry.registerComponent; 

AppRegistry.registerComponent = ( appKey,component)=>{
    return originRegister(appKey,function(){
        const OriginAppComponent = component();  //之前被注册过的根组件

        return class extends Component {
            render() {
                return (  //返回一个全新的根组件
                    <View style={styles.container}
                          onStartShouldSetResponder={()=>Toast.hide()}//手动隐藏toast
                    >
                        <OriginAppComponent/>
                        <Toast/>  //这里添加自定义Toast全局组件
                    </View>
                );
            };
        };
    })
};

⚠️2019/10/29补充:
缺点是根组件动态添加的组件无法使用react-redux/connect,因为被<Redux.Provider>包裹的组件与其是平级关系。
⚠️2021/08/17补充:
基于第3条可知,registerComponent主要是用来注册根组件并接收原生端传递过来的参数,所以重复注册会导致原生端传递的参数丢失
所以建议使用setWrapperComponentProvider实现⬇️

setWrapperComponentProvider()

1.包装根组件[2]
上述我们提到使用registerComponent动态改变根组件,如果你有尝试过会发现RootView.show()方法不能用在constructor内。除了使用registerComponent封装一个高阶组件返回新的根组件,还可以直接使用setWrapperComponentProvider来包装根组件。

AppRegistry.setWrapperComponentProvider(function() {
  return function RootSiblingsWrapper(props) {
    return (
      <View style={styles.container}>
        {props.children}
        <Toast /> //插入自定义组件
      </View>
    );
  };
});

registerHeadlessTask/startHeadlessTask

registerHeadlessTask是在APP未开启的情况下在JavaScript层运行任务的方法。例如:同步新数据,处理推送通知或播放音乐。
常和startHeadlessTask一起使用。

参考

@1uokun 1uokun added the blog 日常开发笔记 label Aug 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blog 日常开发笔记
Projects
None yet
Development

No branches or pull requests

1 participant