0

I'm currently refactoring a CheckIn process app. I want to trigger a different modal to open and change 2 states when a status returns 200. I keep coming across "Unhandled Promise Rejection" when I try to combine async await with try catch block. I refactored the code from fetch().then() and I am not sure I did this correctly. I tried 2 different ways so far and I'm still getting the same error. Is there a better way to handle this?

class CheckIn extends Component {
    _reservationOpacity = new Animated.Value(0)

    constructor(props) {
        super()

        this.state = {
            modalVisible: false,
            modalOtherVisible: false,
            seatAvailable: false,
            refreshing: false,
            data: null,
        }
    }
    
    onScanPress = (payload) => {
        class HttpError extends Error {
            constructor(response) {
                super(`${response.status} for ${response.url}`)
                this.name = "HttpError"
                this.response = response
            }
        }

        async function loadJson(url, payload) {
            let response = await fetch(url, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify(payload),
            })
            if (response.status == 200) {
                
                //
                // I get "Possible Unhandled Promise Rejection" with  
                // TypeError: Cannot read property 'setState' of undefined
                // for both instances
                //
                // Trial 1:
                
                // const res = response.json()
                
                // if (res.isCheckedIn === "check-in") {
                //     console.log("Seat is available check-in---\n", data)

                //     this.setState({ data: res, seatAvailable: true })
                //     this.showResponse()
                //     return res
                // }
                // if (res.isCheckedIn === "checked-out") {
                //     console.log("User is already checked-in---\n", data)
                    
                //     this.showOtherResponse()
                //     return res
                // } 
                
                //
                // Trial 2:
                //
                // return response.json().then((res) => {
                //  if (res.isCheckedIn === "check-in") {
                //      console.log("Seat is available check-in---\n", data)

                //      this.setState({ data: res, seatAvailable: true })
                //         this.showResponse()
                //  }
                //     if (res.isCheckedIn === "checked-out") {
                //         console.log("User is already checked-in---\n", data)
                        
                //         this.showOtherResponse()
                //     } 
                // })
            }else {
                throw new HttpError(response)
            }
        }

        this.setState({ refreshing: true }, async () => {
            let check
            try {
                check = await loadJson(
                    `http://localhost:9000/api/check`,
                    payload
                )
            } catch (err) {
                if (err instanceof HttpError && err.response.status == 404) {
                    console.log("404")
                    this.setState(
                        {
                            data: null,
                            seatAvailable: false,
                            refreshing: false,
                        },
                        this.showResponse()
                    )
                } else {
                    // unknown error, rethrow
                    throw err
                }
            }
            return check
        })
    }

    showOtherResponse() {
        this.setState({ modalOtherVisible: true }, () => {
            Animated.timing(this._reservationOpacity, {
                toValue: 1,
                duration: 200,
                useNativeDriver: true,
            }).start()
        })
    }

    showResponse() {
        this.setState({ modalVisible: true }, () => {
            Animated.timing(this._reservationOpacity, {
                toValue: 1,
                duration: 200,
                useNativeDriver: true,
            }).start()
        })
    }


    render() {
        const {
            modalVisible,
            modalOtherVisible,
            data,
            seatAvailable,
        } = this.state

        return (
            <>
                <View style={styles.container}>
                    <View style={styles.buttonContainer}>
                        <TouchableOpacity
                            style={styles.buttonTouchable}
                            onPress={() =>
                                this.onScanPress({
                                    email: "name@gmail.com",
                                    name: "Jeff",
                                    description:
                                        "Location #1",
                                })
                            }
                        >
                            <Text style={styles.buttonText}>
                                Location #1
                            </Text>
                        </TouchableOpacity>
                    </View>
                </View>

                {modalOtherVisible && (
                    <Animated.View
                        style={{
                            ...StyleSheet.absoluteFill,
                            zIndex: 3,
                            opacity: this._reservationOpacity,
                        }}
                    >
                        <Response
                            data={data}
                            seatAvailable={seatAvailable}
                        />
                    </Animated.View>
                )}

                {modalVisible && (
                    <Animated.View
                        style={{
                            ...StyleSheet.absoluteFill,
                            zIndex: 3,
                            opacity: this._reservationOpacity,
                        }}
                    >
                        <ResponseRedux
                            data={data}
                        />
                    </Animated.View>
                )}
            </>
        )
    }
}

export default CheckIn
Etep
  • 547
  • 2
  • 8
  • 21
  • 1
    Nothing to do with promises or async/await actually. In the `async function loadJson`, `this` does not refer to the instance. You'd need to `await loadJson.call(this, …)`. Or just don't call `setState` from `loadJson`, but only return the result object, and handle the modal stuff where you call it. – Bergi Jan 17 '21 at 02:54
  • @Bergi thanks for the help `await loadJson.call(this, …)` fixed the issue! – Etep Jan 17 '21 at 03:03

0 Answers0