在React Native中将数据从一个组件传递到另一个

时间:2019-05-20 09:13:58

标签: react-native

我正在为单个应用设置子域URL。子域名将在第一次输入。它保存到异步存储中,并且需要从通用组件中检索它

使用const不能正常工作。

这是部分完成的代码。在另一个组件函数内部需要baseURL和socketURL。如何从那里访问这些常量?

index_new.js

    import * as React from 'react';
    import { View } from 'react-native';
    import AsyncStorage from '@react-native-community/async-storage';
    import Login from "../screens/common/login/login/login";

    export default class App extends React.Component {
        constructor(props) {
            super(props);

            this.state = {
                sub_domain: '',
            };
        }

        async getSchoolCode() {
            let sub_domain = '';
            try {
                sub_domain = await AsyncStorage.getItem('SCHOOL_CODE') || ''
            } catch (error) {
            }
            return sub_domain;
        };

        async setSubdomain() {
            const sub_domain = await this.getschoolcode()
            await this.setState({ sub_domain })
        }

        getBaseUrl() {
            return `http://${this.state.sub_domain}.vidhyadhan.in:81/`;
        }

        getSocketIoUrl() {
            return `http://${this.state.sub_domain}.vidhyadhan.in:8080/`;
        }

        async componentDidMount() {
            await this.setSubdomain();
        }

        render() {
            const baseUrl = this.getBaseUrl();
            const socketIoUrl = this.getSocketIoUrl();
            const extraProps = {
                baseUrl,
                socketIoUrl
            }

            return (
                <View>
                    <Login {...extraProps} />
                </View>
            )
        }
    }

Login.js

    import React, { Component } from 'react'
    import {
        Alert,
        Keyboard,
        Text,
        View,
        TextInput,
        TouchableHighlight,
        Image,
        ActivityIndicator,
        StatusBar,
    } from 'react-native'
    import config from "../../../../config";
    import styles from './style'
    import { Icon } from "react-native-elements";
    import Toaster from '../../../../components/toaster'
    import AsyncStorage from '@react-native-community/async-storage';

    class Login extends Component {
        constructor(props) {
            super(props);
            this.state = {
                credentials: {
                    schoolcode: "",
                    email: "",
                    password: "",
                },
                loading: false,
                school_code: '',
            };
        }


        async getschoolcode() {
            let school_code = '';
            try {
                school_code = await AsyncStorage.getItem('SCHOOL_CODE') || ''
            } catch (error) {
            }
            return school_code;
        };

        updateText(text, field) {
            let newCredentials = Object.assign(this.state.credentials);
            newCredentials[field] = text;
            // setState should be done like this
            this.setState({
                credentials: newCredentials
            })

            if(field == 'schoolcode'){
                AsyncStorage.setItem('SCHOOL_CODE', text);
                this.getschoolcode().then((keyValue) => {
                    this.state.school_code = keyValue;
                    console.log(this.state.school_code);
                });
            }
        }
        async login() {
            Keyboard.dismiss();
            let credentials = this.state.credentials;
            if (this.state.credentials.schoolcode == '' || this.state.credentials.email == '' || this.state.credentials.password == '') {
                Toaster.toast('Please Enter a valid UserName and Password', '#d30000')
            } else {
                const that = this;
                credentials.email = that.state.credentials.email;
                this.setState({ loading: !this.state.loading });
                const new_url = this.props.baseUrl;
                fetch(config.baseURL + 'mobileapi/get_token/?username=' + `${that.state.credentials.email}` + '&password=' + `${that.state.credentials.password}`, {
                    method: 'POST',
                    headers: {
                        Accept: 'application/json',
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        credentials: credentials,
                    }),
                })
                    .then((response) => response.json())
                    .then(responseJson => {
                        if (responseJson.confirmation === "success") {
                            AsyncStorage.setItem('USER_ID', responseJson.data.user_id.toString());
                            this.setState({ loading: !this.state.loading });
                            setTimeout(() => {
                                this.props.navigation.navigate("Home")
                            }, 500);
                        } else {
                            this.setState({ loading: !this.state.loading });
                            setTimeout(() => {
                                Toaster.toast('Please Enter a valid UserName and Password', '#d30000')
                                // throw new Error(responseJson.message);
                            }, 500);

                        }
                    })
                    .catch((err) => {

                        //stop loading
                        this.setState({ loading: !this.state.loading });

                        setTimeout(() => {
                            if (JSON.stringify(err.message) === JSON.stringify('Network request failed')) {
                                Toaster.toast('Please check your internet connection or try again later', '#d30000')
                            }
                        }, 500);

                    })

            }
        }

        render() {
            const loginText = (this.state.loading) ? 'Loading' : 'Login';
            return (
                <View style={styles.container}>
                    <StatusBar backgroundColor="#2383c9"
                               translucent={true}
                               hidden={false}/>
                    <Image source={require('../../../../assets/images/icons/logo.png')}
                        style={{ width: 99, height: 99, margin: 5, }} />
                    <Text style={{ fontSize: 20, margin: 20, color: "#ffffff" }}>Vidhyadhan</Text>

                    <View style={styles.inputContainer}>
                        <Image style={styles.inputIcon}
                               source={require('../../../../assets/images/icons/username.png')} />
                        <TextInput style={styles.inputs}
                                   placeholder="School-Code"
                                   underlineColorAndroid='transparent'
                                   onChangeText={text => {
                                       this.updateText(text, 'schoolcode')
                                   }} value={this.state.schoolcode}
                                   autoCorrect={false}
                                   autoCapitalize={"none"}
                        />
                    </View>


                    <View style={styles.inputContainer}>
                        <Image style={styles.inputIcon}
                            source={require('../../../../assets/images/icons/username.png')} />
                        <TextInput style={styles.inputs}
                            placeholder="Username"
                            keyboardType="email-address"
                            underlineColorAndroid='transparent'
                            onChangeText={text => {
                                this.updateText(text, 'email')
                            }} value={this.state.email}
                            autoCorrect={false}
                            autoCapitalize={"none"}
                        />
                    </View>
                    <View style={styles.inputContainer}>
                        <Image style={styles.inputIcon}
                            source={require('../../../../assets/images/icons/password.png')} />
                        <TextInput style={styles.inputs}
                            placeholder="Password"
                            secureTextEntry={true}
                            underlineColorAndroid='transparent'
                            onChangeText={text => {
                                this.updateText(text, 'password')
                            }}
                            value={this.state.password}
                            autoCorrect={false}
                            secureTextEntry />
                    </View>

                    <TouchableHighlight style={[styles.buttonContainer, styles.loginButton]}
                        onPress={this.login.bind(this)} >
                        <View style={{ justifyContent: 'center', flex: 1, flexDirection: 'row' }}>
                            {this.state.loading === false ?
                                <Icon name='login' type='entypo' size={16} color='white' /> :
                                <ActivityIndicator size="small" color="#ffffff" />}
                            <Text style={styles.loginText}> {loginText} </Text>
                        </View>
                    </TouchableHighlight>
                </View>
            );
        }
    }

    export default Login;


1 个答案:

答案 0 :(得分:0)

首先,您没有正确设置状态。然后,您尝试两次设置状态。

这是一种更好的方法:

import * as React from 'react';
import { View } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      sub_domain: '',
    };
  }

  async getSchoolCode() {
    let sub_domain = '';
    try {
      sub_domain = await AsyncStorage.getItem('sub_domain') || ''
    } catch (error) {
    }
    return sub_domain;
  };

  async setSubdomain() {
    const sub_domain = await this.getschoolcode()
    await this.setState({ sub_domain })
  }

  getBaseUrl() {
    return `http://${this.state.sub_domain}.vidhyadhan.in:81/`;
  }

  getSocketIoUrl() {
    return `http://${this.state.sub_domain}.vidhyadhan.in:8080/`;
  }

  async componentDidMount() {
    await this.setSubdomain();
  }

  render() {
    const baseUrl = this.getBaseUrl();
    const socketIoUrl = this.getSocketIoUrl();

    return (
      <View/>
    );
  }
}

根据评论,您的渲染方式如下:

render() {
  const baseUrl = this.getBaseUrl();
  const socketIoUrl = this.getSocketIoUrl();
  const extraProps = {
    baseUrl,
    socketIoUrl
  }

  return (
    <View>
      <MyFirstComponent {...extraProps} />
      <MySecondComponent {...extraProps} />
    </View>
  )
}

MyFirstComponent中,您可以使用this.props.baseUrlthis.props.socketIoUrl