0

I am using below versions

  1. react-native-router-flux ^3.39.1
  2. react-native 0.44.0

I expecting that will call API which I am using with "fetch" Have used componentDidMount but it's showing another error

undefined is not an object (evaluating 'this._component.getScrollableNode')

But I am getting below error outputs

enter image description here enter image description here

Steps to reproduce

  1. Create three scene using router flux (In my case App, Login, Home)
  2. Use ScrollView for creating the Login.js Create a button
  3. using TouchableHighlight after that call the fetch with a function using onPress like onPress={ () => this.fetchData() }

Below code, I am using for App.js

import React, { Component } from 'react';
import {
    View,
    Text,
    StyleSheet,
    AsyncStorage,
} from 'react-native';

import Login from './components/Login'
import Register from './components/Register'
import Home from './components/Home'
import { Scene, Router, TabBar, Modal, Schema, Actions, Reducer, ActionConst } from 'react-native-router-flux'

const reducerCreate = params=>{
    const defaultReducer = Reducer(params);
    return (state, action)=>{
        console.log("ACTION:", action);
        return defaultReducer(state, action);
    }
};

export default class App extends Component {

    constructor(props, context) {
        super(props, context);
        this.state = {
            logged: false,
            loading: true,
        };
    };

    componentWillMount(){
        self = this;
        AsyncStorage.getItem('token')
        .then( (value) =>{
            if (value != null){
                this.setState({
                    logged: true,
                    loading: false,
                });
            }
            else {
                this.setState({
                    loading: false,
                })
            }
        });
    };

    render() {
        if (this.state.loading) {
            return <View><Text>Loading</Text></View>;
        }
        return (
            <Router>
                <Scene hideNavBar={true} key="root">
                    <Scene key="logIn" component={Login} title="Login" initial={!this.state.logged}/>
                    <Scene key="regisTer" component={Register} title="Register"/>
                    <Scene key="home" component={Home} title="home"  initial={this.state.logged}/>
                </Scene>
            </Router>
        )
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
});

And below code, using for Login.js

/* @flow */

import React, { Component } from 'react';

import {
    View,
    StyleSheet,
    Image,
    ScrollView,
    TextInput,
    Text,
    TouchableHighlight,
    Alert,
} from 'react-native';
import { Container, Content, InputGroup, Input, Icon, Item } from 'native-base';
import Button from 'react-native-button'
import {Actions} from 'react-native-router-flux'
import ResponsiveImage from 'react-native-responsive-image'

export default class Login extends Component {

    constructor(props){
        super(props)
        this.state = {
            email: '',
            password: '',
            data: '',
        }
    }

    fetchData() {
        fetch('http://allstariq.tbltechnerds.com/api/login/?username=andress&password=23434')
        .then((response) => response.json())
        .then((responseData) => {
            this.setState({
                data: responseData.movies,
            });
        })
        .done();
    }

    render() {
        return (
            <View style={styles.container}>

            <ScrollView>

                <View style={ styles.logoContainer }>

                    <View style={{flexDirection: 'row',}}>
                        <ResponsiveImage
                        source={require('../assets/logo.png')}
                        initWidth="300"
                        initHeight="160" />
                    </View>

                </View>

                <View style={ styles.formContainer }>
                    <Item>
                        <Icon active name='mail' />
                        <Input
                            onChangeText={(text) => this.setState({email: text})}
                            value={this.state.email}
                            placeholder='Email'/>
                    </Item>

                    <Item>
                        <Icon active name='key' />
                        <Input
                            onChangeText={(text) => this.setState({password: text})}
                            value={this.state.password}
                            placeholder='Password'/>
                    </Item>
                    <TouchableHighlight
                        style={ styles.loginButton }
                        onPress={ () => this.fetchData() }>
                        <Text style={ styles.btnText}>Login</Text>
                    </TouchableHighlight>
                </View>

                <View style={ styles.bottomContainer }>
                    <Text style={ styles.cenText }>Dont worry if you haven't an account yet . . </Text>
                    <Text
                    style={ styles.blueText}
                    onPress={ Actions.regisTer }
                    >Register Now</Text>
                </View>

            </ScrollView>

            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    logoContainer: {
        flex: .5,
        padding: 10,
        justifyContent: 'center',
        alignItems: 'center',
    },
    logoItem: {
        width: null,
        height: null,
        resizeMode: 'cover',
    },
    formContainer: {
        flex: 4,
        padding: 10,
    },
    inputelm: {
        marginBottom: 10,
        backgroundColor: '#999',
        borderWidth: 0,
        fontSize: 20,
        color: '#FFF',
        fontFamily: 'AmaticSC-Bold',
    },
    loginButton: {
        borderRadius: 3,
        marginBottom: 20,
        marginTop: 20,
        paddingLeft: 10,
        paddingRight: 10,
        backgroundColor: '#2196f3',
        elevation: 4,
    },
    signupButton: {
        borderRadius: 3,
        marginBottom: 20,
        marginTop: 20,
        paddingLeft: 10,
        paddingRight: 10,
        backgroundColor: '#7cb342',
        elevation: 4,
    },
    btnText: {
        textAlign: 'center',
        color: '#FFF',
        fontSize: 30,
        lineHeight: 40,
    },
    blueText: {
        textAlign: 'center',
        color: '#2196f3',
        fontSize: 20,
        lineHeight: 40,
    },
    bottomContainer: {
        flex: 1,
        padding: 10,
    },
    cenText: {
        textAlign: 'center',
        fontSize: 16,
    },
});

What is the actual way to use fetch with react-native-router-flux? I am new to react, please help me.

Tareq Aziz
  • 341
  • 1
  • 10
  • 25

3 Answers3

1

well, its a couple of months late but the problem here is that your fetchData method hasn't got access to this because when you declare a method like this:

fetchData() {

}

Under the hood react is creating a function this way:

this.fetchData = function() {

}

when you declare a function using the function keyword, everything between {} will have its own "this" and your method will not have access to the "this" of the component context.

That is the reason why you are getting the "undefined", because you are calling "this.setState" inside the promise returned by fetch, so the error is not fetch, but this.

To solve this issue you could just define your method this way:

fetchData = () => {

}

And because the functions defined with a fat arrow do not create their own scope, the component "this" will be available from inside your method.

EnriqueDev
  • 1,207
  • 2
  • 12
  • 25
0

Did you try maybe to import the library?

Import fetch from "fetch";
Tzook Bar Noy
  • 11,337
  • 14
  • 51
  • 82
0

You have not imported the fetch function, import it from the node-fetch module like

import fetch from 'node-fetch'
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400