0

我刚开始使用 react native 构建应用程序,并在同一页面上创建了一个基本的登录功能,视图和登录功能称为HomeScreen.js. 但是我从网上阅读了文章,我被告知最好将逻辑代码与视图分开,功能必须在单独的页面上,视图也必须在不同的页面上。请我需要有关如何做到这一点的帮助

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Image, ActivityIndicator, Alert} from 'react-native';
import {Icon, Header, Left, Content, Container, Form, Input, Item, Button, Label, Toast} from 'native-base'
import SettingsScreen from './SettingsScreen';



class HomeScreen extends Component{

    constructor(props){
        super(props)
        this.state={
            showLoader: false,
        }
    }


    static navigationOptions={
        header: null,
        drawerIcon:(
            <Image source={require('../assets/imgs/logo.jpg')}
            style={{height:24, width:24}}/>
        )
    }

  render() {
    return (
        <Container>
        <Header>
            <Left>
                <Icon name="ios-menu" onPress={() =>
                  this.props.navigation.toggleDrawer()}/>
            </Left>
        </Header>

        <Content style={{backgroundColor:'white'}}>
        <Content style={{alignContent:"center", top:100}}>

        { <Image  source={require('../assets/imgs/logo.jpg')}
        style={{height:200, width:200, alignSelf:"center"}}/> }

        <Form>
            <Item stackedLabel>
            <Label >
                Username
            </Label>
            <Input onChangeText={(text=>this.setState({userName:text}))} autoCapitalize = 'none'/>
            </Item>

            <Item stackedLabel last>
            <Label >
                Password
            </Label>
            <Input onChangeText={(text=>this.setState({passWord:text}))}  secureTextEntry={true}  />
            </Item>

            <Content style={{padding:20}}>
            <Button onPress={this.userLogin.bind(this)} iconRight block  primary disabled={!this.state.userName} disabled={!this.state.passWord}>
                <Icon name='arrow-forward' />
                <Text style={{color:'white'}}>Login</Text>
            </Button>
            </Content>

            <Content>
                <ActivityIndicator style={{padding:5}}
                animating={this.state.showLoader}
                size="small"
                />
            </Content>

        </Form>

        </Content>
        </Content>
        </Container>
    );
  }

  userLogin(){ 
      this.setState({showLoader: true});
      fetch('http://api_endpoint.com/login.php',{
        method: 'POST',
        body :JSON.stringify({
            username: this.state.userName,
            password: this.state.passWord
          })
      }).then((response)=>{
        return response.json()
      }).then((response)=>{
          console.log(JSON.stringify(response.message))
          this.setState({showLoader: false})
          if(response.message==='0'){
            Toast.show({
                text: "Wrong Username or Password",
                buttonText: "Try Again",
                type: "danger",
                duration: 4000
              })
          }else{
            this.props.navigation.push('Settings');
          }
      }).catch((error) => {
        this.setState({showLoader: false})
        Alert.alert(
            'Error!',
            'Connection Failed, Try again later',
            [
              {text: 'Ok'}
            ],
            { cancelable: false }
          )

      });
  }
}

export default HomeScreen;
4

2 回答 2

0

你已经做了一个很好的开始。请参阅 Udemy 或其他网站上提供的适当视频教程,以获得良好的开端。由于您的问题更客观,我们无法在这里解释全部内容。获取有关 redux 的知识,以便您可以将逻辑移动到 redux reducer 和 action。还要尝试了解可以移动视图并使主要组件精简的功能组件。

https://www.udemy.com/react-native-the-practical-guide/?start=0

您可以参加上述课程以获得更好的知识。

于 2018-11-12T09:56:02.390 回答
0

在这种情况下,非常清楚哪些代码是视图的一部分,哪些代码在执行 AJAX 逻辑。该userLogin功能显然不是表象的;您可以从 10 英尺外看到代码与上面的代码完全不同。

但是,它与应用程序的其余部分有点相关,因为它执行与 UI 相关的操作Toast,例如显示和导航。

分离此代码的一种方法是将函数一分为二。将 AJAX 调用移至另一个(非 React)文件,并删除与 React 相关的任何内容。它只会异步返回一个结果。然后您视图中的其余代码部分可以相应地响应(例如显示 Toast、导航或调用 setState)。

下一步可能是将函数的剩余位移动到容器组件中。该组件将提供登录功能,并将其结果存储在自己的状态中。然后它将这些结果的相关部分传递给 HomeScreen 组件。就像是:

import HomeScreen from './homeScreen';
import loginUser from '../apiClient';

class HomeScreenContainer extends Component {
  doLogin = () => {
    this.setState({loginInFlight: true});
    loginUser(userName, password)
    .then(result=>
      this.setState({loginInFlight: false, loginResult: result});
      if (result.loginSucceeded) {
        this.props.navigation.push('Settings');
      }
    }).catch((error) => {
        this.setState({showLoader: false, loginError: true})    
    });
  }
  render() {
    return (
      <HomeScreen 
        loginFunction={this.doLogin} 
        showLoader={this.state.loginInFlight} 
        shouldShowToast={this.state.loginResult.invalidLogin} 
        shouldShowError={this.state.loginError} 
      />
    )
}
于 2018-11-12T10:03:31.033 回答