React Native - 有条件地渲染视图

时间:2017-04-12 21:50:01

标签: react-native react-native-ios mobx

我有一个反应原生的应用程序,我正在努力。现在我希望它有两个视图。登录页面和主页面。到目前为止,它看起来像这样:

index.ios.js

import React, { Component } from 'react';
import {
  AppRegistry,
  Dimensions,
  StyleSheet,
  Text,
  TextInput,
  Button,
  TouchableHighlight,
  View
} from 'react-native';
import Scanner from './app/components/Scanner';
import Login from './app/components/Login';
import Store from './app/mobx/store';

export default class TestApp extends Component {
  render() {
    if (Store.loggedIn()){
      return <Scanner />
    } else {
      return <Login store={Store} />
    }
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    backgroundColor: '#114DA0'
  }
});

AppRegistry.registerComponent('TestApp', () => TestApp);

应用/组件/ Login.js

import React, { Component } from 'react';

import {
  StyleSheet,
  Text,
  View,
  TextInput,
  ScrollView
} from 'react-native';
import Container from './Container';
import Button from './Button';
import Label from './Label';
import {observer} from 'mobx-react/native';

@observer
export default class Login extends Component {
  constructor() {
    super();
    this.state = {
      email: '',
      password: '',
      isLoggingIn: false,
      message: ''
    }
    this._userLogin = this._userLogin.bind(this);
  }
  _userLogin() {
    console.log("loggin in...")
    this.setState({isLoggingIn: true, message:''});
    var params = {
        email: this.state.email,
        password: this.state.password
    };
    var formBody = [];
    for (var property in params) {
      var encodedKey = encodeURIComponent(property);
      var encodedValue = encodeURIComponent(params[property]);
      formBody.push(encodedKey + "=" + encodedValue);
    }
    formBody = formBody.join("&");
    fetch("http://example.com:8000/auth/mobile_login", {
        method: "POST",
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: formBody
      })
      .then((response) => {
        return response.json()
      })
      .then((response) => {
        if (response.error) {
          this.setState({message: response.message});
        } else if (response.user) {
          this.props.store.logIn(response.user);
        }
      })
      .then(() => {
        this.setState({isLoggingIn: false})
      })
      .done();
  }
  render() {
    return (
        <ScrollView style={styles.scroll}>
          <Container>
            <Label text="Email" />
            <TextInput
              style={styles.textInput}
              onChangeText={(email) => this.setState({email})}
            />
          </Container>
          <Container>
            <Label text="Password" />
            <TextInput
              secureTextEntry={true}
              style={styles.textInput}
              onChangeText={(password) => this.setState({password})}
            />
          </Container>
          <Container>
            {!!this.state.message && (
              <Text style={{fontSize: 14, color: 'red', padding: 5}}>
                {this.state.message}
              </Text>
            )}
            <Button
              label="Sign In"
              styles={{button: styles.primaryButton, label: styles.buttonWhiteText}}
              onPress={this._userLogin} />
          </Container>
        </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
  ...
});

应用/组件/ Scanner.js

import React, { Component } from 'react';
import {
  AppRegistry,
  Dimensions,
  StyleSheet,
  Text,
  TouchableHighlight,
  View
} from 'react-native';
import Camera from 'react-native-camera';

export default class Scanner extends Component {
  constructor(){
    super();
    this.onBarCodeRead = this.onBarCodeRead.bind(this);
  }
  onBarCodeRead(e) {
    this.setState({text: e.data});
  }
  render() {
    return (
      <View style={styles.container}>
          <Camera
            ref={(cam) => {
              this.camera = cam;
            }}
            onBarCodeRead={this.onBarCodeRead}
            style={styles.preview}
            aspect={Camera.constants.Aspect.fill}>
          </Camera>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  ...
});

AppRegistry.registerComponent('Scanner', () => Scanner);

两个页面都运行正常,我可以通过登录页面登录我的服务。但是一旦我登录,我怎样才能让root组件呈现Scanner页面?

1 个答案:

答案 0 :(得分:0)

这里的关键是每次调用setState时都会调用render:

  

执行nextState到当前状态的浅层合并。这是   用于从事件处理程序触发UI更新的主要方法   服务器请求回调。   https://facebook.github.io/react/docs/react-component.html#setstate

因此,可以通过检查此loggedIn状态并有条件地呈现内容来实现基于状态更改(在这种情况下,用户登录)更新组件的内容。

请考虑以下代码作为示例:

import React, { Component } from 'react';
import './App.css';


const ContentA = () => (
    <div>
        <h1>Filled with content A</h1>
    </div>
);

const ContentB = () => (
    <div>
        <h1>Filled with content B</h1>
    </div>
);


class App extends Component {

    state = {
        loggedIn: false
    };

    logIn = () => {
        this.setState({
            loggedIn: !this.state.loggedIn
        })
    };

    render() {

    const content = this.state.loggedIn ? <ContentA/> : <ContentB/>;
    return (
        <div>
            {content}
            <button onClick={this.logIn}>Clicky</button>
        </div>
    );
  }
}

export default App;

每次单击该按钮时,都会调用setState,并根据this.state.loggedIn的值重新呈现该组件。

希望这有帮助,祝你好运!