React Native Posting / Fetching to backend

时间:2018-06-05 04:37:17

标签: reactjs react-native android-emulator fetch fetch-api

我无法通过Android模拟器将数据发布到带有React Native的快速后端。该应用程序的目标是允许客户发布微型任务请求,如家务和草坪护理,其中所有数据将存储到AWS RDS MySQL服务器。另一方面,有自由职业者可以通过Feed查看客户帖子。 (有关此处的更多背景视图:https://askfavr.com)现在您已了解问题的背景。

import React, { Component } from 'react';
import {
    StyleSheet, Text, View, Image,
    TextInput, KeyboardAvoidingView,
    TouchableOpacity, AsyncStorage, ScrollView
} from "react-native";


export default class App extends React.Component {
    state = {
        request: {
            C_Name: '', //this is a placeholder for the addRequest()  method
            Email: '',
            Phone: '',
            Category: '',
            Time_Length: '',
            Street: '',
            City: '',
            C_State: '',
            Zip: '',
            Finish_Before: '',
            Price: '',
            Details: ''
        }
    }

    /* Just like getRequests, addRequest does exactly what its named as well. It adds a request
      to the MySQL database following the initialization of the request state. The addRequest()
      uses the post method which then returns are query string containing the new data submitted */
    addRequest = _ => {
        const { request } = this.state;
        //query string set to remote server  
        fetch(`http://192.168.56.1:4000/requests/add?C_Name=${request.C_Name}&Email=${request.Email}&Phone=${request.Phone}&Category=${request.Category}&Time_Length=${request.Time_Length}&Street=${request.Street}&City=${request.City}&C_State=${request.C_State}&Zip=${request.Zip}&Finish_Before=${request.Finish_Before}&Price=${request.Price}&Details=${request.Details}`)
            .catch(err => console.error(err))
    }

    render() {
        const { request } = this.state; //set state for addRequest()
        return (
            <KeyboardAvoidingView behavior='padding' style={styles.wrapper}>
                <Text style={styles.header}> Yardwork Request </Text>
                <ScrollView>
                    <TextInput
                        style={styles.TextInput} placeholder='Name:' value={request.C_Name}
                        onChangeText={Name => this.setState(request.C_Name)}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='Email:' value={request.Email}
                        onChangeText={e => this.setState({ request: { ...request, Email: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='Phone:' value={request.Phone}
                        onChangeText={e => this.setState({ request: { ...request, Phone: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='Category:' value={request.Category}
                        onChangeText={e => this.setState({ request: { ...request, Category: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='Time of Job:' value={request.Time_Length}
                        onChangeText={e => this.setState({ request: { ...request, Time_Length: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='Street:' value={request.Street}
                        onChangeText={e => this.setState({ request: { ...request, Street: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='City:' value={request.City}
                        onChangeText={e => this.setState({ request: { ...request, City: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='State:' value={request.C_State}
                        onChangeText={e => this.setState({ request: { ...request, C_State: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='Zip:' value={request.Zip}
                        onChangeText={e => this.setState({ request: { ...request, Zip: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='Complete By:' value={request.Finish_Before}
                        onChangeText={e => this.setState({ request: { ...request, Finish_Before: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='Price:' value={request.Price}
                        onChangeText={e => this.setState({ request: { ...request, Price: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TextInput
                        style={styles.TextInput} placeholder='Details:' value={request.Details}
                        onChangeText={e => this.setState({ request: { ...request, Details: e.target.value } })}
                        underlineColorAndroid='black'
                    />
                    <TouchableOpacity
                        style={styles.btn}
                        onPress={this.addRequest}>
                        <Text> Request </Text>
                    </TouchableOpacity>
                </ScrollView>
            </KeyboardAvoidingView>
        );
    }
}

const styles = StyleSheet.create({
    wrapper: {
        flex: 1,
    },
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: '#FFF',
        paddingLeft: 40,
        paddingRight: 40,
    },
    header: {
        fontSize: 24,
        marginTop: 25,
        color: '#000000',
        fontWeight: 'bold',
    },
    TextInput: {
        alignSelf: 'stretch',
        padding: 16,
        marginBottom: 20,
        borderRadius: 12,
        color: '#000000',
        fontSize: 16,
        //backgroundColor: '#fff',
    },
    btn: {
        alignSelf: 'stretch',
        backgroundColor: 'green',
        padding: 20,
        borderRadius: 12,
        alignItems: 'center',
    },
    small: {
        fontSize: 15,
        color: '#000000',
        paddingTop: 10,
    },
});

当我尝试在本机中运行基本相同的东西时我得到此错误

setState(...)将状态变量的对象更新为或返回状态变量对象的函数

但是在Plain React中我几乎可以使用几乎没有问题的精确代码并轻松发布数据

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

class App extends Component {
    state = {
        requests: [], //null state for the getRequests() method
        request: {
            C_Name: '', //this is a placeholder for the addRequest()  method
            Email: '',
            Phone: '' ,
            Category: '',
            Time_Length:'' ,
            Street:'' ,
            City:'' , 
            C_State:'' ,
            Zip:'' , 
            Finish_Before:'' ,
            Price: '',
            Details: ''
        }
    }

    /* Mounts the "getRequests" to display on the screen, instead of writing the 
  full method within the componentDidMount() 
  componentDidMount() Purpose: this method takes place before rendering to
  essentially change the state of the arrays and variables if they are no
  longer null. */
    componentDidMount() {
        this.getRequests();
    }

    getRequests = _ => {
        fetch('http://192.168.56.1:4000/requests')
        .then( response => response.json())
        .then(response => this.setState({ requests: response.data}))
        .catch( err => console.error(err))
    }

    /* Just like getRequests, addRequest does exactly what its named as well. It adds a request
    to the MySQL database following the initialization of the request state. The addRequest()
    uses the post method which then returns are query string containing the new data submitted */
    addRequest =_ => {
        const { request } = this.state;
        //query string set to remote server  
        fetch(`http://localhost:4000/requests/add?C_Name=${request.C_Name}&Email=${request.Email}&Phone=${request.Phone}&Category=${request.Category}&Time_Length=${request.Time_Length}&Street=${request.Street}&City=${request.City}&C_State=${request.C_State}&Zip=${request.Zip}&Finish_Before=${request.Finish_Before}&Price=${request.Price}&Details=${request.Details}`) 
        .then(this.getRequests)
        .catch(err => console.error(err))
    }


    //Fields of Data for a FAVR Request: 
    //idyard_record, time_posted, C_Name, Email, Phone, Category, Time_Length, Street, City, C_State, Zip, Finish_Before, Price
    //Details, RequestID, Proposals
    renderRequest = ({ idyard_record, C_Name, Category }) => 
        <div key={idyard_record}>{C_Name}: <b>{Category} </b><br/><br/> </div> //displays all requests from the MySQL data similar to a flatlist
    render() {
        const { requests, request} = this.state; //set state for getRequests() && getRequest()


        const mainDiv = {
            align: 'center',
            justifyContent: 'center',
            flex: '1',
            margin: '2%'
        }
        const divStyle = {
            margin: '2%',
        };

        const inputBorder = {
            borderColor: 'lightgrey',
            padding: '5px',
            marginTop: '1%',
            marginLeft: '1%'
        }

        return (
            <div className="App" style={mainDiv} >
                {requests.map(this.renderRequest)}
                <div>
                    <div style={divStyle} > 
                        <label style={{align: 'left'}} > Name: </label> 
                        <input style={inputBorder} value={request.C_Name} 
                        onChange={e => this.setState({ request: {...request, C_Name: e.target.value}})} /> 
                    </div>
                    <div style={divStyle} >
                        <label> Email: </label> 
                        <input style={inputBorder} value={request.Email} 
                        onChange={e => this.setState({ request: {...request, Email: e.target.value}})} /> 
                    </div> 
                    <div style={divStyle} >
                        <label style={{textAlign: 'left'}} > Phone: </label> 
                        <input style={inputBorder} value={request.Phone} 
                        onChange={e => this.setState({ request: {...request, Phone: e.target.value}})} /> 
                    </div> 
                    <div style={divStyle} >
                        <label> Category: </label> 
                        <input style={inputBorder} value={request.Category} 
                        onChange={e => this.setState({ request: {...request, Category: e.target.value}})} /> 
                    </div> 
                    <div style={divStyle} >
                        <label> Time of Job: </label> 
                        <input style={inputBorder} value={request.Time_Length} 
                        onChange={e => this.setState({ request: {...request, Time_Length: e.target.value}})} /> 
                    </div> 
                    <div style={divStyle} >
                        <label> Street: </label> 
                        <input style={inputBorder} value={request.Street} 
                        onChange={e => this.setState({ request: {...request, Street: e.target.value}})} /> 
                    </div>
                    <div style={divStyle} >
                        <label> City: </label> 
                        <input style={inputBorder} value={request.City} 
                        onChange={e => this.setState({ request: {...request, City: e.target.value}})} /> 
                    </div>  
                    <div style={divStyle} >
                        <label> State: </label> 
                        <input style={inputBorder} value={request.C_State} 
                        onChange={e => this.setState({ request: {...request, C_State: e.target.value}})} /> 
                    </div>  
                    <div style={divStyle} >
                        <label> Zip: </label> 
                        <input style={inputBorder} value={request.Zip} placeholder='55901' 
                        onChange={e => this.setState({ request: {...request, Zip: e.target.value}})} /> 
                    </div> 
                    <div style={divStyle} >
                        <label> Complete By: </label> 
                        <input type="datetime-local" style={inputBorder} value={request.Finish_Before} placeholder='55901' 
                        onChange={e => this.setState({ request: {...request, Finish_Before: e.target.value}})} /> 
                    </div>
                    <div style={divStyle} >
                        <label> Price: </label> 
                        $<input type="number" style={inputBorder} value={request.Price} placeholder='$20'
                        onChange={e => this.setState({ request: { ...request, Price:  e.target.value }})} />
                    </div> 
                    <div style={divStyle} >
                        <label> Details: </label> 
                        <textarea rows={3} style={inputBorder} value={request.Details}
                        onChange={e => this.setState({ request: { ...request, Details:  e.target.value }})} />
                    </div> 
                    <button onClick={this.addRequest}> Request FAVR </button> 
                </div> 
            </div>
        );
    }
}

export default App;

有没有人有解决此问题的建议?我知道后端不是问题,因为简单的反应应用程序可以发布到它,并且模拟器/普通反应应用程序可以显示来自MySQL数据库的数据没有问题。

image of react native error

2 个答案:

答案 0 :(得分:0)

问题似乎是这一个:

    onChangeText={Name => this.setState(request.C_Name)}

这一行在React Native代码中,但不是简单的React代码,所以这是两者之间的差异。你应该传递setState()一个对象,例如:

    this.setState({ request: {...request, C_Name: e.target.value}})

类似于你对其他人所做的。

答案 1 :(得分:0)

我能够解决这个问题,改变了三件事:

  1. 在React Native中,您无法单独使用状态,您必须配置要通过构造函数传递的更改状态项
  2. *所以不要这样:*

    state = {
        request: {
            C_Name: '', //this is a placeholder for the addRequest()  method
            Email: '',
            Phone: '',
            Category: '',
            Time_Length: '',
            Street: '',
            City: '',
            C_State: '',
            Zip: '',
            Finish_Before: '',
            Price: '',
            Details: ''
        }
    }
    

    您必须将状态变量更改为此

    constructor(props) {
    super(props)
    this.state = {
      request: {
        C_Name: '', //this is a placeholder for the addRequest()  method
        Email: '',
        Phone: '',
        Category: '',
        Time_Length: '',
        Street: '',
        City: '',
        C_State: '',
        Zip: '',
        Finish_Before: '',
        Price: '',
        Details: ''
      }
    }
    

    2。 其次,当您使用提交按钮时,我建议使用括号作为提交功能

    而不是

    addRequest = _ => {
        const { request } = this.state;
        //query string set to remote server  
        fetch(`http://192.168.56.1:4000/requests/add?C_Name=${request.C_Name}&Email=${request.Email}&Phone=${request.Phone}&Category=${request.Category}&Time_Length=${request.Time_Length}&Street=${request.Street}&City=${request.City}&C_State=${request.C_State}&Zip=${request.Zip}&Finish_Before=${request.Finish_Before}&Price=${request.Price}&Details=${request.Details}`)
            .catch(err => console.error(err))
    }
    

    您必须将此功能更改为:

    addRequest = () => {
    const { request } = this.state;
    //query string set to remote server  
    fetch(`http://192.168.56.1:4000/requests/add?C_Name=${request.C_Name}&Email=${request.Email}&Phone=${request.Phone}&Category=${request.Category}&Time_Length=${request.Time_Length}&Street=${request.Street}&City=${request.City}&C_State=${request.C_State}&Zip=${request.Zip}&Finish_Before=${request.Finish_Before}&Price=${request.Price}&Details=${request.Details}`)
      .catch(err => console.error(err))
    }
    
    1. 最后,您必须正确传递onchange文本。你不能像平常反应一样使用目标价值。
    2. 所以不要使用此

      onChangeText={e => this.setState({ request: { ...request, Email: e.target.value } })}
      

      忽略e.target.value并将其更改为类似的内容(当然,为每个输入使用不同的变量)

      onChangeText={(Email) => this.setState({ request: { ...request, Email: Email } })}
      

      总而言之,确保状态在构造函数下传递,第二次使用() =>代替_ =>,最后确保正确传递输入对象。 请记住.target.value并不像React Native那样使用简单的反应。