React|React native数据通信

  • 导航器传递参数给路由
  • 往导航栏传递参数
  • RN与原生模块通信
导航器传递参数给路由 示例:同导航器内的TestScreen1往TestScreen2传递了两个参数{params1:"1111",params2:"2222"}
APP.js
const taskNavigator = createStackNavigator({ test1:TestScreen1, test2:TestScreen2 })

TestScreen1.js
render() { return ( 第一个界面!

TestScreen2.js
render() { return ( 第二个界面! {"params1 = " + this.props.navigation.state.params.params1} {"params2 = " + this.props.navigation.getParam("params2",2)} {"params3 = " + this.props.navigation.getParam("params3",3)} ); }

获取时可用两种方式,
第一种navigation.getParam(paramName,defaultValue),参数不存在时,取默认值
第二种navigation.state.params. paramName, 如果未指定参数,它的值是 null。

React|React native数据通信
文章图片
20190730_141515.gif
往导航栏传递参数 使用this.props.navigation.setParams({paramName1: paramValue1,paramName2: paramValue2,...})的方式向导航栏传值
在导航栏中使用navigation.getParam(paramName,defaultValue)取值
export default class TestScreen1 extends Component { _paramsValue = https://www.it610.com/article/0; static navigationOptions = ({ navigation }) => { return { title: '第一个界面' + navigation.getParam("param",""), headerLayoutPreset: "center", headerTitleStyle: { fontWeight: 'normal', fontSize: 16, flex: 1, textAlign: 'center' }, headerStyle: { backgroundColor: 'white', elevation: 5, }, }}; render() { return ( 第一个界面! {/*

React|React native数据通信
文章图片
20190730_152051.gif RN与原生模块通信 一.RN 调用安卓代码 经常会用到的场景比如获取一些安卓本地缓存数据等
具体步骤如下:
1.在Android端创建一个继承ReactContextBaseJavaModule的类,实现getName()方法,用来返回RN寻找到该类的名称
public class ClientModule extends ReactContextBaseJavaModule {private ReactContext mReactContext; public ClientModule(ReactApplicationContext reactContext) { super(reactContext); mReactContext = reactContext; }@Override public String getName() { return "ClientModule"; } }

2.创建用于RN调用的方法,用@ReactMethod注解修饰
@ReactMethod public void showToast(String message) { Toast.makeText(mReactContext,message,Toast.LENGTH_SHORT).show(); }

这里创建了一个弹出原生Toast的方法。
3.创建一个实现ReactPackage接口的类,用来管理原生模块的Model,将继承了ReactContextBaseJavaModule的Model添加进去
public class ClientPackage implements ReactPackage { @Nonnull @Override public List createNativeModules(@Nonnull ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new ClientModule(reactContext)); return modules; }@Nonnull @Override public List createViewManagers(@Nonnull ReactApplicationContext reactContext) { return Collections.emptyList(); } }

4.将创建好的ClientPackage添加到包管理列表中
public class MainApplication extends Application implements ReactApplication {public static Context mContext; private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), new RNGestureHandlerPackage(), new ClientPackage() ); }@Override protected String getJSMainModuleName() { return "index"; } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; }@Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); mContext = getApplicationContext(); } }

5.在RN中调用
导入组件
import {NativeModules} from 'react-native'; const clientModule = NativeModules.ClientModule;

在需要弹出的地方调用

React|React native数据通信
文章图片
20190730_164743.gif 二. Promise 机制与安卓原生代码通信 Promise 机制需要在原生代码中创建一个桥接方法,当方法的最后一个参数书一个Promise对象时,该方法会返回给js一个与之对应的Promise对象
原生代码,在ClientModule中新增一个桥接方法
@ReactMethod public void rnCallNativePromise(String message, Promise promise){ Toast.makeText(mReactContext,message,Toast.LENGTH_SHORT).show(); //得到组件名称 String componentName = getCurrentActivity().getComponentName().toString(); promise.resolve(componentName); }

在js中调用

React|React native数据通信
文章图片
20190730_172909.gif 三.使用callback回调方式与安卓原生代码通信 原生代码,在ClientModule中新增一个桥接方法,传入一个成功和失败的Callback回调
@ReactMethod public void rnCallNativeCallback(Callback success, Callback error) { try { success.invoke(100, 200); } catch (Exception e) { error.invoke(e.getMessage()); } }

在js端调用

React|React native数据通信
文章图片
20190730_174652.gif 四.使用RCTDeviceEventEmitter与原生通信 RCTDeviceEventEmitter类似一个EventBus消息传递机制,有发送方和接收方,与EventBus类似,在接收方需要注册监听,并在生命周期结束后取消监听
1.通过ReactApplicationContextgetJSModule方法获取到RCTDeviceEventEmitter, 调用emit(eventName, paramss)方法发送一个消息事件
因并不是原生代码所有的地方都有reactContext,所有建立一个工具类,在rn的model被加载后给工具类的静态变量reactContext赋值
ClientModule:
public ClientModule(@Nonnull ReactApplicationContext reactContext) { super(reactContext); mReactContext = reactContext; ToReactNativtUtil.reactContext = reactContext; }

ToReactNativtUtil:
public class ToReactNativtUtil { public static ReactApplicationContext reactContext; public static void sendEvent(String eventName, @Nullable WritableMap paramss) { if(reactContext == null)return; reactContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit(eventName, paramss); } }

需要发送消息的地方
这里是直接在MainActivity启动后延时2s给RN发送一个登陆成功的事件,并传递一个userName参数
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UiInstance.getInstance().postRunnableDelayedToHandler(new Runnable() { @Override public void run() { //给RN发送一个loginSucc的事件 WritableMap writableMap= Arguments.createMap(); writableMap.putString("userName","wenny"); ToReactNativtUtil.sendEvent("loginSucc",writableMap); } },2000); }

2.在RN中通过DeviceEventEmitter来监听事件
import { DeviceEventEmitter } from 'react-native'; componentDidMount() { DeviceEventEmitter.addListener('loginSucc', (writableMap) => { Alert.alert('接收到 loginSucc userName :', writableMap.userName) }); } componentWillUnmount() { //移除监听 this.subscription.remove(); }

React|React native数据通信
文章图片
20190730_182814.gif 五.利用getLaunchOptions方法向js传递一个Bundle类型的数据 这种传递方式适用场景有:A(原生Activity)进入B(ReactActivity)时需要将A中的某些参数传递给B的js组件中。
原生端发送:
@Override protected ReactActivityDelegate createReactActivityDelegate() { return new ReactActivityDelegate(this, getMainComponentName()) { @Override protected ReactRootView createRootView() { return new RNGestureHandlerEnabledRootView(MainActivity.this); } @Nullable @Override protected Bundle getLaunchOptions() { Bundle bundle = new Bundle(); bundle.putString("newsItemId","123"); bundle.putString("newsItemName","新闻标题1"); return bundle; } }; }

在js端的入口组件中获取,并通过导航器传参给路由
App.js
class App extends Component { appContainer constructor(props) { super(props); var newsItemId = this.props.newsItemId; var newsItemName = this.props.newsItemName; let stack = createStackNavigator({ test1: TestScreen1, test2: TestScreen2 }, { initialRouteParams: { newsItemId: newsItemId, newsItemName: newsItemName }, }) this.appContainer = createAppContainer(stack) } render() { return ; } } AppRegistry.registerComponent("VideoProject", () => App);

【React|React native数据通信】TestScreen1.js
{navigation.getParam("newsItemId","-") +' ' + navigation.getParam("newsItemName","-")}

    推荐阅读