为啥我不能让我的 RN 应用程序在本地运行以与本地 api 服务器通信?

Posted

技术标签:

【中文标题】为啥我不能让我的 RN 应用程序在本地运行以与本地 api 服务器通信?【英文标题】:Why can't I get my RN app running locally to talk to a local api server?为什么我不能让我的 RN 应用程序在本地运行以与本地 api 服务器通信? 【发布时间】:2019-06-25 06:08:05 【问题描述】:

我有一个 React Native 前端和一个 Rails API 后端,但我似乎无法成功登录。

当我重新加载 RN 模拟器时,我确实收到以下消息:

RCTBridge 需要 dispatch_sync 来加载 RCTDevLoadingView。这可能 导致死锁

老实说,我不知道这是否相关。

我确实知道相关的错误是当我得到:

服务器:TypeError:网络请求失败

我可以采取哪些步骤来解决此问题?

我确实可以访问前端和后端代码库。

我想知道问题是否出在这个app/containers/LoginScreen/index.js

import React from 'react';
import  ActivityIndicator, StatusBar, Text, View, Linking, Image, TouchableWithoutFeedback, TouchableOpacity, Platform, Keyboard  from 'react-native';
import Analytics from 'react-native-analytics-segment-io';
import KeyboardSpacer from 'react-native-keyboard-spacer';
import PropTypes from 'prop-types';
import  connect  from 'react-redux';
import _ from 'lodash';
import  Images, Colors  from '../../themes';
import  loginUser, getMeQuestions, getMeAnswers, pullOnLoadData, setLoggingIn  from '../../reducers/userReducer';
import  getModuleInfo, getLessonInfo  from '../../reducers/lessonModuleReducer';
import  FrigateButton, FrigateTextInput, HeaderBackButton, NavRightIcon  from '../../components';
import styles from './styles';

class LoginScreen extends React.Component 
  static getDerivedStateFromProps(nextProps, prevState) 
    if (!nextProps.id) 
      return ;
    
    if (nextProps.id && nextProps.lessons.length > 0 && nextProps.modules.length > 0) 
      if (!prevState.loadedData) 
        nextProps.pullOnLoadData(nextProps.id);
        if (!nextProps.signedCurrentTerms) 
          Analytics.identify('user_id',  id: nextProps.id, email: nextProps.email );
          nextProps.navigation.navigate('TOSPP');
         else 
          Analytics.identify('user_id',  id: nextProps.id, email: nextProps.email );
          nextProps.navigation.navigate('TabNavigator');
        
        return  ...prevState, loadedData: true ;
      
    
    return ;
  

  constructor(props) 
    super(props);
    this.state = 
      username: '',
      password: '',
      loadedData: false,
    ;
    this.loginPressed = this.loginPressed.bind(this);
  

  loginPressed() 
    Analytics.track('Login Pressed',  email: this.state.username );
    this.props.setLoggingIn(true);
    Keyboard.dismiss();
    this.props.login(
      this.state.username,
      this.state.password,
    );
  

  render() 
    return (
      <View
        testID="signupScreen"
        style=styles.mainContainer
      >
        <StatusBar barStyle="light-content" />
        <Image source=Images.background style=styles.backgroundImage />
        <View style=styles.brand>
          <Image source=Images.logo style=styles.logoImage />
        </View>
        !this.props.token &&
          <View style=styles.textInputs>
            <FrigateTextInput
              onChangeText=text => this.setState( username: text )
              label="EMAIL"
              placeholder="EMAIL"
              value=this.state.username
              keyboardType="email-address"
            />
            <FrigateTextInput
              onChangeText=text => this.setState( password: text )
              label="PASSWORD"
              placeholder="PASSWORD"
              secureTextEntry
              value=this.state.password
            />
            <TouchableOpacity
              onPress=() => 
                // Analytics.track('Forgot Password Pressed',  email: this.state.username );
                this.props.navigation.navigate('ForgotPassword');
                // Linking.openURL('http://thirdelement.herokuapp.com/users/password/new')
              
            >
              <View style= alignItems: 'flex-end', paddingRight: 20, paddingTop: 5 >
                <Text style= color: 'white' >Forgot Password?</Text>
              </View>
            </TouchableOpacity>
          </View>
        
        this.props.token &&
          <View style=styles.activityIndicator>
            <ActivityIndicator size="large" />
          </View>
        
        !this.props.token &&
          <View style=styles.actionButtons>
            <FrigateButton
              title="Log In"
              disabled=!_.every([
                this.state.username,
                this.state.password,
              ], Boolean)
              onPress=this.loginPressed
            />
          </View>
        
        Platform.OS === 'ios' &&
          <KeyboardSpacer />
        
      </View>
    );
  


LoginScreen.propTypes = 
  login: PropTypes.func.isRequired,
  navigation: PropTypes.shape(
    goBack: PropTypes.func,
  ).isRequired,
  token: PropTypes.string,
;

LoginScreen.defaultProps = 
  token: null,
;

LoginScreen.navigationOptions = props => (
  title: 'Welcome Back',
  headerLeft: <HeaderBackButton onPress=() => props.navigation.goBack() />,
  headerRight: <NavRightIcon />,
  headerStyle: 
    backgroundColor: 'black',
    shadowColor: 'transparent',
    borderBottomWidth: 0,
  ,
  headerTintColor: Colors.thirdElementOrange,
  headerTitleStyle: 
    fontWeight: 'bold',
  ,
);


const mapStateToProps = state => (
  email: state.user.email,
  id: state.user.id,
  token: state.user.token,
  lessons: state.lessonModules.lessons,
  modules: state.lessonModules.modules,
  signedCurrentTerms: state.user.signedCurrentTerms,
);

const mapDispatchToProps = dispatch => (
  login: (u, p) => dispatch(loginUser(u, p)),
  getModules: () => dispatch(getModuleInfo()),
  getLessons: () => dispatch(getLessonInfo()),
  getMeQuestions: () => dispatch(getMeQuestions()),
  getMeAnswers: () => dispatch(getMeAnswers()),
  pullOnLoadData: id => dispatch(pullOnLoadData(id)),
  setLoggingIn: value => dispatch(setLoggingIn(value)),
);

export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(LoginScreen);

我进入Info.plist 并配置为:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

这给了我另一个类似于这篇文章的错误:

What is the meaning of 'No bundle URL present' in react-native?

我尝试按照它的建议这样做:

我跑了rm -rf ios/build/; kill $(lsof -t -i:8081); react-native run-ios,但它什么也没做。

【问题讨论】:

你最好分享一些代码行 xD 【参考方案1】:

对于 android 模拟器,您必须使用您的 IP 地址而不是 localhost。例如,使用:

fetch('http://000.000.000:3000/login', 
  method: 'POST',
  headers: 
    Accept: 'application/json',
    'Content-Type': 'application/json',
  ,
  body: params,
)

您还必须允许 http:// 请求。打开 info.plist (ProjectFolder->ios->ProjectFolder->info.plist) 并在前面添加以下内容:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

见:https://***.com/a/48946478/10987825

【讨论】:

Noah,Mac 模拟器呢? 您还必须对所有常规的 http 请求。查看更新的答案

以上是关于为啥我不能让我的 RN 应用程序在本地运行以与本地 api 服务器通信?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 scrollLeft JS 函数不能在我的本地 wordpress 网站上运行?

C - 为啥我不能从本地主机外部访问我的服务器?

为啥我的 ReactJS 应用程序在本地运行但不在 Azure 中运行?

为啥我不能在 docker 中构建这个 nuxtjs 应用程序,而本地构建工作?

为啥我不能使用 Webview 加载我的本地页面

如果我可以从我的私人 IP 地址访问本地文件,为啥我不能从我的公共 IP 地址访问本地文件?