react-native开发问题以及处理

杜俊爽
2023-12-01

React Native

搭建开发环境

npm i -g react-native-cli 

react-native init demo01

react-native run-ios

获取屏幕宽度

import { 
Dimensions,
StatusBar,
SafeAreaView,
Text
} from 'react-native';
import React from 'react';

const App = () => React$Node = ()=>{
  return(
  <>
  	<StatusBar>  
  		<SafeAreaView>
  			<Text>
  				获取屏幕的宽度:{Dimensions.get('window').width + '\n'}
  				获取屏幕的高度:{Dimensions.get('window').height + '\n'}
  				获取屏幕的分辨率:{Dimensions.get('window').scale + '\n'}
  			</Text>
 		  </SafeAreaView>
 	 	</StatusBar>
  </>
  )
}

区分平台

import { Platform } from 'react-native'
import React form 'react'
const App = () => React$Node = ()=>{
  console.log(Platform.OS)// ios || android
  // 还有很多Platform的用法
  return(
  <>
  </>
  )
}

pod install问题

pod install --verbose --no-repo-update
# 被墙了,需要这样去安装
# 再修改GitHub的host
# https://juejin.cn/post/6844904193170341896

# Flipper的一个依赖有问题,更新到最新版本可解决 修改Podfile中的use_filpper那行,添加版本。https://github.com/reactnativecn/react-native-website/issues/370

clashX 设置sock5代理端口https://www.bokezhu.com/2021/03/04/731.html

git 配置socks代理https://blog.csdn.net/wuquan0625/article/details/47401235

使用ts模板项目

https://www.react-native.cn/docs/typescript#using-custom-path-aliases-with-typescript

npm install -g expo-cli
expo init MyTSProject

解决初始化TypeScript模板的RN项目报错问题

1.删除旧版本 react-native-cli
 
npm uninstall -g react-native-cli
 
2.重新安装来自"react-native-community"的cli库 :
 
npm i -g @react-native-community/cli
 
3.重新初始化项目即可:
 
npx react-native init MyApp --template react-native-template-typescript

react-native集成dva

文章https://www.jianshu.com/p/e7ffeb0e5971

项目https://github.com/Tzng/ReactNativeDva

列表组件

单组的列表建议使用FlatList(有重用机制)

多组的列表建议使用SectionList

网络请求

联调:在ios虚拟机快捷键呼出菜单control+command+z,再点击Debug

react-native run-ios --simulator 'iPhone 12'

React Native无法调出Dev Menu
  • react-native原生支持fetch进行网络请求的处理。
  • 也可以使用第三方库axios
使用react-native-debugger调试react-native
debug工具
rn网络图片无法显示问题
  • https://stackoverflow.com/questions/47035899/how-come-my-image-is-not-showing-react-native
  • https://www.zhihu.com/question/38046813
pre_install do |installer|
  puts("Image fix for ios14: remove this when upgradeing to >= 0.63.3")
  find = "_currentFrame.CGImage;"
  replace = "_currentFrame.CGImage ;} else { [super displayLayer:layer];"
  op = `sed -ie "s/#{find}/#{replace}/" ../node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m`
  puts("Image fix for ios14 done")
end

把这段话加到 podfile 最后面

react-navigation

一、安装

yarn add @react-navigation/native
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

二、概念

将所以需要导航的页面全部放在这个容器里面NavigationContainer

import { NavigationContainer } from '@react-navigation/native';

使用"栈"来控制导航

//yarn add @react-navigation/stack
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import Home from '@/pages/Home';
import Details from '@/pages/Details';
import { navigationRef } from './NavigationUtil';
import NavigatorsTest from '@/pages/NavigatorsTest';

const Stack = createStackNavigator();

export default function AppNavigators() {
  return (
    <NavigationContainer ref={navigationRef}>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={Home} />
        <Stack.Screen name="Details" component={Details} />
        <Stack.Screen name="NavigatorsTest" component={NavigatorsTest} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

navigation-prop

this.props.navigation

  • navigate('组件路由名字',{paramName:value}):跳转到对应的页面,想要再点击跳转回原来页面会没有反应。
  • push('组件路由名字',{paramName:value}):只要需要跳转就可以跳转。(区别于navigate)不断地向导航容器执行压栈操作。
  • goBack():返回上一次跳转页面。
  • popToTop():回到首页。

获取传递的参数:

  1. this.props.navigation.getParam(paramName)
  2. this.props.navigation.state.params

Header buttonsConfiguring the header bar

头部标题:

function StackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ title: 'My home' }}
      />
    </Stack.Navigator>
  );
}

头部导航:

function StackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{
          headerTitle: props => <LogoTitle {...props} />,
          headerRight: () => (
            <Button
              onPress={() => alert('This is a button!')}
              title="Info"
              color="#fff"
            />
          ),
        }}
      />
    </Stack.Navigator>
  );
}

createBottomTabNavigator

底部导航栏:

//yarn add @react-navigation/bottom-tabs
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
function MyTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}

使用嵌套导航器尝试此屏幕选项

const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();

function HomeStackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="A"
        component={A}
      />
      <Stack.Screen
        name="B"
        component={B}
      />
    </Stack.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator
        <Tab.Screen name="ScreenOne" component={HomeStackScreen} />
       // .....
      </Tab.Navigator>
    </NavigationContainer>
 )
}

二次封装axios

使用请求拦截器和响应拦截器。

import axios from 'axios';
import AsyncStorage from '@react-native-community/async-storage';
import { store } from '@/App';

const instance = axios.create({
  baseURL: 'http://localhost:3000/api',
  headers: {
    'Content-Type': 'application/json',
    Accept: '*/*',
    Connection: 'keep-alive',
  },
  transformRequest: [
    data => {
      data = JSON.stringify(data);
      return data;
    },
  ],
});

instance.defaults.timeout = 2500;

// http request 拦截器
instance.interceptors.request.use(
  async config => {
    const token = await AsyncStorage.getItem('token');
    if (token) {
      // 判断是否存在token,如果存在的话,则每个http header都加上token
      config.headers.Authorization = `Bearer ${token}`; //请求头加上token
    }
    return config;
  },
  err => {
    return Promise.reject(err);
  }
);

// http response 拦截器
instance.interceptors.response.use(
  response => {
    //拦截响应,做统一处理
    if (response.data.code) {
      switch (response.data.code) {
        case 401:
          store.dispatch({ type: 'app/save', payload: { isLogin: false } });
      }
    }
    return response;
  },
  // 接口错误状态处理,也就是说无响应时的处理
  error => {
    return Promise.reject(error.response.status); // 返回接口返回的错误信息
  }
);

export default instance;

rn表单处理

react-native-gifted-form

tcomb-form-native

rc-form

@ant-design/react-native问题

使用Toast组件的时候出现 Unrecognized font family ‘antoutline’ 报错,解决办法?

https://github.com/oblador/react-native-vector-icons/issues/965#issuecomment-547649424

进入 node_modules/@ant-design/icons-react-native/fonts 目录, 复制 `antfill.ttf` 和 `antoutline.ttf` 到 `Xcode Project -> Resources folder` 

打开Xcode,将两个文件添加到依赖中.

将两个文件 添加到 `info.plist` -> `Fonts provided by application` 配置中。

运行 `react-native link @ant-design/icons-react-native` 应该可以正常的解决这个问题,如果不行你应该查看为什么这个不起作用。

https://blog.csdn.net/ioth5/article/details/104253511

React-native本地图片无法显示问题

https://blog.csdn.net/wo_dxj/article/details/109604077

更新最新Xcode之后,跑之前RN项目,本地图片资源怎么都加载不出来,各种找寻解决办法,终于找到问题了:直接上解决办法

首先找到RCTUIImageViewAnimated.m 文件

修改267行代码

- (void)displayLayer:(CALayer *)layer
{
  if (_currentFrame) {
    layer.contentsScale = self.animatedImageScale;
    layer.contents = (__bridge id)_currentFrame.CGImage;
  }
}


修改成

- (void)displayLayer:(CALayer *)layer
{
  if (_currentFrame) {
    layer.contentsScale = self.animatedImageScale;
    layer.contents = (__bridge id)_currentFrame.CGImage;
  } else {
    [super displayLayer:layer];
  }
}

就OK了,希望能帮助遇到类似问题的小伙伴们

图片选取和裁剪

react-native-image-crop-picker

react-native-image-picker

使用oss上传图片

ali-oss

最全阿里云node.js上传

koa需要安装依赖才能获取form-data的参数boundary(使用koa-body中间件)(这里不建议使用koa-bodyparser中间件)

 multipart/form-data; boundary=something

//对于多部分实体,boundary 是必需的,其包括来自一组字符的1到70个字符,已知通过电子邮件网关是非常健壮的,而不是以空白结尾。它用于封装消息的多个部分的边界。

解决bug:使用axios发送form-data数据的时候,不需要设置'Content-Type': 'multipart/form-data',如果强制设置content-type的话,multipart/form-data后面就会自动添加boundary的解析。

 类似资料: