react-native中开发中遇到的一些问题

字数 5862 阅读 685 喜欢 3
  • 首先开发一款app,算是一个中级的app,有考虑使用现在比较火热的flutter,但是考虑到后面需要集成的东西比较多,比如微信,whatsapp,Facebook,twitter等外国的一些主流app,另外一方面是任务比较着急,需要快速开发,所以综合考虑下来还是选择使用之前使用过的react-native进行开发。
  • 另外一个原因就是react-native经过这么长时间的沉淀,轮子和工具肯定是不会少的,
  • 对于ts支持友好

react-navigation简单解析

首先在开发过程中,对于路由的选择的就是现在比较流行的react-navigation。
React Navigation的诞生,源于React Native社区对基于Javascript的可扩展且使用简单的导航解决方案的需求。
React Navigation是Facebook,Expo和React社区的开发者们合作的结果:它取代并改进了React Native生态系统中的多个导航库,其中包括Ex-Navigation,React Native的Navigator和NavigationExperimental组件。

  • StackNavigator 一次只渲染一个页面,并提供页面之间跳转的方法。 当打开一个新的页面时,它被放置在堆栈的顶部
  • TabNavigator - 渲染一个选项卡,让用户可以在几个页面之间切换
  • DrawerNavigator - 提供一个从屏幕左侧滑入的抽屉

举一个🌰
当前应用有三个tab,分别为home,order,main三个页面,代码如下


const HomeStack = createStackNavigator(
  {
    [EHomeRoutes.Home]: Home,
  },
  {
    navigationOptions({ navigation }) {
      return {
        tabBarLabel: i18n.t(LANGUAGE_KEYS.HOME),
        tabBarIcon: options => <Ionicon name="ios-home" size={23} {...getTabIconStyles(options)} />
      }
    }
  }
)

const OrderStack = createStackNavigator(
  {
    [EOrderRoutes.Order]: Order,
  },
  {
    navigationOptions({ navigation }) {
      return {
        tabBarLabel: i18n.t(LANGUAGE_KEYS.ORDER),
        tabBarIcon: options => <Ionicon name="ios-order" size={23} {...getTabIconStyles(options)} />
      }
    }
  }
)

const MainStack = createStackNavigator(
  {
    [EMainRoutes.Main]: Main,
    [EMainRouter.Login]: Login
  },
  {
    navigationOptions({ navigation }) {
      return {
        tabBarLabel: i18n.t(LANGUAGE_KEYS.Main),
        tabBarIcon: options => <Ionicon name="ios-main" size={23} {...getTabIconStyles(options)} />
      }
    }
  }
)

在上面的代码可以看到我将登陆页面login挡在MainStack里面,运行应用会发现一个问题,应用启动,当前显示为home页面,我们通过tab跳转到main页面,然后通过main在跳转到login页面,在login页面逻辑处理正确后我们应该跳回到home页面,但是当我们点击tab再次跳转到main页面我们会发现没有去main页面,而是直接去到了login页面,回头再去看代码,会发现我们将login页面放在了MainStack里面,这样会导致我们当前页面的stack还在login里面,所以出现了这个bug,那么如何解决这个问题呢,最简单的方法就是我们使用dispatch重写了reset或者直接使用reset方法

const resetAction = StackAction.reset({
  index: 0,
  actions: [NAvigationActions.navigate({ routeName: EMainRouter.Login})],

});

//使用
this.props.navigation.dispatch(resetaction)

// 或者直接使用reset
navigation.reset([NavigationActions.navigate({ routeName: EMainRouter.Login })], 0)

这个bug产生的主要原因是在mainstack里面login-view在当前stack的顶层,当我们选择跳转到mainstack的时候,stack返回给我们的login-view所以会显示在login页面

关于在react-native中集成微信授权登陆分享等功能

  1. 我们需要去微信开发平台去申请移动应用,一般审核时间在两天左右。审核通过后我们可以拿到一个appid和一个appsecret
  2. 然后我们在工程里面按住按钮react-native-wechat并且link这个包
  3. 安卓中需要添加一个WechatEntryActivity.java类,方便获取微信授权以及分享权限
    workspace.png
package your.package.wxapi;
import android.app.Activity;
import android.os.Bundle;

import com.theweflex.react.WeChatModule;

public class WXEntryActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    WeChatModule.handleIntent(getIntent());
    finish();
  }
};

在AndroidManifest.xml中添加

<!-- 微信Activity -->
<activity android:name=".wxapi.WXEntryActivity" android:label="@string/app_name" android:exported="true" />
  1. 使用
// 分享朋友圈
private async shartLine() {
  let result = await Wechat.shareToTimeline({
    type: 'text',
    description: 'hello, Wechat'
  });
  console.log('share text message to time line successful:', result);
}
// 分享图片
private async shareImage() {
  Wechat.shareToSession({
    thumbImage: 'https://static.jinhaidi.cn/form.jpeg',
    type: 'imageUrl',
    imageUrl: 'https://static.jinhaidi.cn/abc4e5422cd7297d3806989ed33cc6b3.png'
  })
}
// 分享链接
private async shareArticle() {
  Wechat.shareToSession({
    title: '微信好友测试链接',
    description: '我是来自app文章的分享',
    thumbImage: 'https://static.jinhaidi.cn/abc4e5422cd7297d3806989ed33cc6b3.png',
    type: 'news',
    webpageUrl: 'https://jinhaidi.cn/article/5cbc2fa3f1e4e1318d24c3e7'
  })
}

// 授权
// scope 应用授权作用域,如获取用户个人信息则填写snsapi_userinfo
// state 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击)
// 建议第三方带上该参数,可设置为简单的随机数加session进行校验

const codeData = await wechat.sendAuthRequest('snsapi_userinfo', 'test')

// 获取accessToken
// 开放平台申请的appid 和 appSecret 加上上一步获取的code
const resToken = await getAccessToken({
  appid: WxAppId,
  secret: WxAppSecret,
  grant_type: 'authorization_code',
  code: codeData.code
})
const userInfo = await getUnionId({
  access_token: resToken.access_token,
  openid: resToken.openid
})

参数正确无误的情况下可以获取到微信用户信息

关于ios方面的微信授权需要添加权限

  1. 用xcode打开你的项目, 右键点击左侧项目目录Libraries文件夹 ➜ Add Files to <...>
    a.png
  2. b.去node_modules ➜ react-native-wechat ➜ ios ➜ 选择 RCTWeChat.xcodeproj
    b.png
  3. c.在工程Build Phases ➜ Link Binary With Libraries中添加libRCTWeChat.a(直接拖拽过去)
    c.png
  4. 在工程target的Build Phases->Link Binary with Libraries中加入以下库文件:
    SystemConfiguration.framework
    CoreTelephony.framework
    libsqlite3.0
    libc++
    libz
  5. 点击TARGETS 下的项目名 -> info ,添加你的 申请的 微信 AppID到 "URL type"的"URL Schema"处
    d.png
  6. iOS9 以上,添加 微信白名单
    e.png
  7. 编辑info.plist
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>weixin</string>
    <string>wechat</string>
</array>
  1. 在你项目的AppDelegate.m添加以下代码,启动[LinkingIOS]
#import <React/RCTLinkingManager.h>

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
  return [RCTLinkingManager application:application openURL:url
                            sourceApplication:sourceApplication annotation:annotation];
}