Реагировать на исходную проводку / выборку в бэкэнд - PullRequest
0 голосов
/ 05 июня 2018

У меня проблемы с отправкой данных в экспресс-бэкэнд с React Native через эмулятор Android.Цель приложения - предоставить клиентам возможность отправлять запросы на выполнение микрозадач, например, домашние дела и уход за газонами, где все данные будут храниться на сервере AWS RDS MySQL.С другой стороны, есть фрилансеры, которые могут просматривать сообщения клиентов через фид.(Для получения дополнительной информации о фоновом режиме здесь: 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,
    },
});

, когда я пытаюсь запустить, по сути, то же самое, в программе native native я получаю эту ошибку

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 без проблем.

изображение собственной реакции реакции

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Мне удалось решить проблему, изменив три вещи:

  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. Во-вторых, когда вы используете кнопку отправки, я советую использовать скобки для функции отправки

вместо этого

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))
}
Наконец, вы должны правильно передать текст обмена.Вы не можете использовать целевое значение, как если бы вы использовали обычную реакцию.

Поэтому вместо этого

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, как с простой реакцией.

0 голосов
/ 05 июня 2018

Проблематичным представляется следующий:

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

Эта строка находится в собственном коде React, но не в простом коде React, так что в этом разница между ними.Вы должны передавать setState() объект, что-то вроде:

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

аналогично тому, что вы делаете для других.

...