How to pass data from screen to screen from flat list item

How do i able to pass the list items from first screen to the third screen, i am able to pass data on to the second screen but not the third screen. What i'm trying to achieve is how do i able to edit the list item on the third screen and inside the edit text input get the data and update. By the way, i'm using flat list item, because list view is deprecated. Below are my codes and screenshots.

First Screenshot enter image description here

Second screenshot enter image description here

Third screenshot enter image description here

First screenshot coding

class SecondScreen extends Component {
constructor(props){
    super(props);
    this.state = {
        loading: true,
        email: '',
        name: '',
        title: '',
        description: '',
        error: '',
        dataSource: [],
        isFetching: false
    }
}

onPress(item){
    this.props.navigation.navigate(
        'DetailsScreen',
        {item},
    );
}

renderItem = ({ item }) => {
    return (
        <TouchableOpacity style={{ flex: 1, flexDirection: 'row', 
marginBottom: 3}}
            onPress={() => { this.onPress(item) }}>
            <View style={{ flex: 1, justifyContent: 'center', marginLeft: 
5}}>
                <Text style={{ fontSize: 18, color: 'green', marginBottom: 
15}}>
                    {"ID - "+item.id}
                </Text>
                <Text style={{ fontSize: 18, color: 'green', marginBottom: 
15}}>
                    {"Title - "+item.title}
                </Text>
                <Text style={{ fontSize: 16, color: 'red'}}>
                    {"Description - "+item.description}
                </Text>
            </View>
        </TouchableOpacity>
    )
}

renderSeparator = () => {
    return (
        <View
            style={{height: 1, width: '100%', backgroundColor: 'black'}}>
        </View>
    )
}

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

            <Text style={{textAlign: 'center'}}> No job available.</Text>

        </View>

    );
}

handleBackButton = () => {
    Alert.alert(
        'Exit App',
        'Exiting the application?', [{
            text: 'Cancel',
            onPress: () => console.log('Cancel Pressed'),
            style: 'cancel'
        }, {
                text: 'OK',
                onPress: () => BackHandler.exitApp()
        },],{
            cancelable: false
        }
    )
    return true;
} 

componentDidMount(){

    this.getAvailableJob()

    BackHandler.addEventListener('hardwareBackPress', 
this.handleBackButton);
} 

getAvailableJob() {
    const headers = {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + this.props.token
    };

    axios({
        method: 'GET',
        url: 'http://192.168.1.201:8000/api/jobs',
        headers: headers,
    }).then((response) => {
        console.log('response3',response)
        console.log('response4',this.props.token)
        this.setState({
            dataSource: response.data,
            isFetching: false
        });
    }).catch((error) => {
        console.log(error);
        this.setState({
            error: 'Error retrieving data',
            loading: false
        });
    });
}

componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', 
this.handleBackButton);
}

onRefresh() {
    this.setState({ isFetching: true }, function() { this.getAvailableJob() 
});
}

render() {
    const { container, emailText, errorText } = styles;
    const { loading, email, name, error, title, description } = this.state;

    return(
        <View style={container}>
            <FlatList
                data={this.state.dataSource}
                onRefresh={() => this.onRefresh()}
                refreshing={this.state.isFetching}
                renderItem={this.renderItem}
                keyExtractor={(item, index) => index.toString()}
                ListEmptyComponent={this.ListEmptyView}
                ItemSeparatorComponent={this.renderSeparator}
            />
        </View>
    ); 
}
}

export default withNavigation(SecondScreen);

Second screenshot coding

class DetailsScreen extends React.Component {

handleBackButton = () => {
    this.props.navigation.popToTop();
    return true;
} 

componentDidMount(){
    BackHandler.addEventListener('hardwareBackPress', 
this.handleBackButton);
}

componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', 
this.handleBackButton);
}

onPress(item){
    this.props.navigation.push(
        'EditDetailsScreen',
        {item},
    );
}

render() {
    const { backButton } = styles;

    let item = this.props.navigation.state.params.item;

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

            <View style={[styles.container2, { backgroundColor: 'yellow' }, 
styles.hiddenContainer]}>
                <Text style = { styles.TextStyle }> ID { 
this.props.navigation.state.params.item.id }</Text>
            </View>

            <Text style = { styles.TextStyle }> Title { 
this.props.navigation.state.params.item.title }</Text>
            <Text style = { styles.TextStyle }> Description { 
this.props.navigation.state.params.item.description }</Text>
                <TouchableOpacity
                    style = {styles.submitButton}
                    onPress = {() => { this.onPress(item) }}>
                    <Text style = {styles.submitButtonText}> Edit </Text>
                </TouchableOpacity>
        </View>
    );
}
}
export default withNavigation(DetailsScreen);

Third screenshot coding

class EditDetailsScreen extends React.Component {

handleTitle = (text) => {
    this.setState({ title: text })
}

handleDescription = (text) => {
    this.setState({ description: text })
}

handleBackButton = () => {
    this.props.navigation.popToTop();
    return true;
} 

componentDidMount(){
    BackHandler.addEventListener('hardwareBackPress', 
this.handleBackButton);
}

componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', 
this.handleBackButton);
}

updateJobDetails = () => {
    const headers = {
        'Accept': 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Bearer ' + this.props.token
    };

    axios({
        method: 'PUT',
        url: 'http://192.168.1.201:8000/api/jobs',
        headers: headers,
    }).then((response) => {
        this.setState({
            title: response.data,
            description: response.data,
            loading: false
        });
    }).catch((error) => {
        console.log(error);
        this.setState({
            error: 'Error retrieving data',
            loading: false
        });
    });
}

render() {

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

            <View style={[styles.container2, { backgroundColor: 'yellow' }, 
styles.hiddenContainer]}>
                <Text style = { styles.TextStyle }> ID { 
this.props.navigation.state.params.item.id }</Text>
            </View>

            <Text style = { styles.TextStyle }> Title { 
this.props.navigation.state.params.item.title }</Text>
            <Text style = { styles.TextStyle }> Description { 
this.props.navigation.state.params.item.description }</Text>

            <TextInput style = {styles.input}
                underlineColorAndroid = "transparent"
                placeholder = "Edit Title"
                placeholderTextColor = "#9a73ef"
                autoCapitalize = "none"
                onChangeText = {this.handleTitle}/>

            <TextInput style = {styles.input}
                underlineColorAndroid = "transparent"
                placeholder = "Edit Description"
                placeholderTextColor = "#9a73ef"
                autoCapitalize = "none"
                onChangeText = {this.handleDescription}/>

            <TouchableOpacity
                style = {styles.submitButton}
                onPress = {this.updateJobDetails}>
                <Text style = {styles.submitButtonText}> Submit </Text>
            </TouchableOpacity>
        </View>
    );
}
}

export default withNavigation(EditDetailsScreen);

I can update using postman but not in react native, and also in postman i had to set the Body to use x-www-form-urlencoded instead of form-data. So how do i able to update in react native? Any help would be much appreciated. Below is my postman screenshot.

Postman enter image description here

Upvotes: 2

Views: 1640

Answers (2)

I've solved the problem by using qs.stringify(data). Below is my updated code.

updateJobDetails = () => {

    url = 'http://192.168.1.201:8000/api/jobs/' + this.props.navigation.state.params.item.id;

    const qs = require('qs');

    const data = {title:this.state.TextInput_Title,
                description:this.state.TextInput_Description};

    const options = {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Authorization': 'Bearer ' + this.props.token
        },
        data: qs.stringify(data),
        url
    }

axios(options).then((response) => {
        console.log('update response',response)
        Alert.alert(
            'Update successful',
            'Your details has been updated', [{
                    text: 'OK',
                    onPress: () => this.props.navigation.popToTop()
            },]
            ,{
                cancelable: false
            }
        )
        this.setState({
            loading: false,

        });

    }).catch((error) => {
        Alert.alert("Please Enter All the Values.");
        console.log(error);
        this.setState({
            error: 'Error retrieving data',
            loading: false
        });
    });
}

render() {

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

            <View style={[styles.container2, { backgroundColor: 'yellow' }, 
styles.hiddenContainer]}>
                <Text style = { styles.TextStyle }> ID { 
this.props.navigation.state.params.item.id }</Text>
            </View>

            <Text style = {styles.TextStyle2}>
                Title: 
            </Text>

                <TextInput style = {styles.input}
                    underlineColorAndroid = "transparent"
                    placeholder = "Edit Title"
                    placeholderTextColor = "#9a73ef"
                    autoCapitalize = "none"
                    value={this.state.TextInput_Title}
                    onChangeText = { TextInputValue => this.setState({TextInput_Title: TextInputValue})}/>


            <Text style = {styles.TextStyle2}>
                Description: 
            </Text>

            <TextInput style = {styles.input}
                underlineColorAndroid = "transparent"
                placeholder = "Edit Description"
                placeholderTextColor = "#9a73ef"
                autoCapitalize = "none"
                value={this.state.TextInput_Description}
                onChangeText = { TextInputValue => 
this.setState({TextInput_Description: TextInputValue})}/>

            <TouchableOpacity
                style = {styles.submitButton}
                onPress = {this.updateJobDetails}>
                <Text style = {styles.submitButtonText}> Submit </Text>
            </TouchableOpacity>
        </View>
    );
}

Upvotes: 0

mahmoudafer
mahmoudafer

Reputation: 1181

A suggestion is to use a state container like react-redux, but if you don't want: you can pass a function in the props like

<renderedItem update={(newVal) => this.setState({ val: newVal})}>

and then in the renderedItem you can call this function with new value like so:

this.props.update(this.state.newVal)

Upvotes: 1

Related Questions