代码之家  ›  专栏  ›  技术社区  ›  Solomon Antoine

响应本地发布/获取到后端

  •  1
  • Solomon Antoine  · 技术社区  · 8 年前

    我在通过android模拟器将数据发布到带有react native的express后端时遇到问题。该应用程序的目标是允许客户发布微任务请求,如家务和草坪护理,所有数据将存储在一个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,
        },
    });
    

    当我试图在react native中运行基本相同的东西时,我会得到这个错误

    setState(…)接受要更新的状态变量对象或返回状态变量对象的函数

    但是在普通的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;
    

    有人有解决这个问题的建议吗?我知道后端不是问题所在,因为plain react应用程序可以发布到它,而emulator/plain react应用程序可以毫无问题地显示mysql数据库中的数据。

    image of react native error

    2 回复  |  直到 8 年前
        1
  •  0
  •   Jayce444    8 年前

    有问题的似乎是这个:

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

    这一行是react本机代码,而不是普通的react代码,所以这是两者之间的区别。你应该路过 setState() 一个物体,比如:

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

    类似于你为其他人做的事。

        2
  •  0
  •   Solomon Antoine    8 年前

    我改变了三件事来解决这个问题:

    1. 在react native中,不能只有状态,必须配置要通过构造函数传递的更改状态项

    *所以不要这样:*

    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。 其次,当您使用submit按钮时,我建议在submit函数中使用括号

    而不是这个

    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文本。你不能像在普通反应中那样使用目标值。

    所以不用这个

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

    无视 e.target.value 把它改成这样(当然,对每个输入使用不同的变量)

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

    总之,确保状态在构造函数下传递,然后使用 () => 对于submit函数而不是 _ => 最后确保正确传递输入对象。 记得 , .target.value 不适用于react native,就像它不适用于普通react一样。