Search code examples
javascriptreactjsfetchstatesetstate

FETCH helper function returns undefined when calling setState()


I have a helper function that uses FETCH to pull data from an API. I'm trying to set the response of the fetch request to my state using setState() but it keeps returning undefined. Here is my helper function: (I realize I'm exposing my keys on the front end but I will adjust if I ever deploy to production)

const authCode = {
    async getAuthCode() {
        const authCodeMatch = window.location.href.match(/code=([^&]*)/)[1];
        await fetch(`https://id.twitch.tv/oauth2/token?client_id=${TWITCH_ID}&client_secret=${TWITCH_SECRET}&code=${authCodeMatch}&grant_type=authorization_code&redirect_uri=${TWITCH_CB}`, {
            method: 'POST',
            mode: 'cors',
            'Access-Control-Allow-Origin':'*',
            credentials: 'same-origin', 
            headers: {
             'Content-Type': 'application/json'
            }
        })
        .then(response => 
            response.json()    
        )
        .then(data => {
            console.log(data.access_token);
            fetch(`https://api.twitch.tv/helix/users?id=43691`, {
                method: 'GET',
                mode: 'cors',
                'Access-Control-Allow-Origin':'*',
                credentials: 'same-origin',
                headers: {
                    'Content-Type': 'application/json',
                    'Client-ID': TWITCH_ID,
                    'Authorization': 'Bearer ' + data.access_token
                }
            })
            .then(response => response.json())
            .then(newdata => {
                console.log(newdata);
                if (!newdata.data) {
                    return [];
                }
                //console.log(newdata.data[0].view_count);
                return newdata.data.map(views => ({
                    view_count: views.view_count
                }))
            })
        })
    }

Everything logs to the console fine so I'm pretty sure I'm mapping through the correct array to parse the data. In any case, here is the returned object in console as well as my component code. In my profile component it just pushes undefined to my state:

// Console response
data: Array(1)
0:
broadcaster_type: "partner"
description: ""
display_name: "Faker"
id: "43691"
login: "faker"
offline_image_url: "https://static-cdn.jtvnw.net/jtv_user_pictures/7d76e34d-3ee3-42c0-a46b-e320d37fcde6-channel_offline_image-1920x1080.jpeg"
profile_image_url: "https://static-cdn.jtvnw.net/jtv_user_pictures/b2eb8a23-d6ad-45aa-bd8e-062133b64452-profile_image-300x300.png"
type: ""
view_count: 81769581
__proto__: Object
length: 1
__proto__: Array(0)

Component

export default class Profile extends Component {

    constructor(props) {
        super(props);

        this.state = {
            viewData: []
        }

        this.handleNewPost = this.handleNewPost.bind(this);

    }

    handleNewPost () {
        authCode.getAuthCode().then(viewcountResults => {
            this.setState({viewData: viewcountResults})
        })
    }

    render() {
        return (
            <div>
                <Container>
                <div className='mt-5'>
                <Button color='success' size='lg' onClick={this.handleNewPost}>
                    Post Data
                </Button>
                </div>
                <div>
                {this.state.viewData.view_count}
                </div>
                </Container>
            </div>
        )
    }

Thanks for any help!


Solution

  • Your function getAuthCode isn't returning a Promise containing the data you're wanting to receive. Also, you can greatly clean up that code by using await instead of a mixture of await and callbacks.

    const authCode = {
        async getAuthCode() {
            const authCodeMatch = window.location.href.match(/code=([^&]*)/)[1];
            let response = await fetch(`https://id.twitch.tv/oauth2/token?client_id=${TWITCH_ID}&client_secret=${TWITCH_SECRET}&code=${authCodeMatch}&grant_type=authorization_code&redirect_uri=${TWITCH_CB}`, {
                method: 'POST',
                mode: 'cors',
                'Access-Control-Allow-Origin':'*',
                credentials: 'same-origin', 
                headers: {
                 'Content-Type': 'application/json'
                }
            });
            const data = await response.json();
            console.log(data.access_token);
    
            response = await fetch(`https://api.twitch.tv/helix/users?id=43691`, {
                method: 'GET',
                mode: 'cors',
                'Access-Control-Allow-Origin':'*',
                credentials: 'same-origin',
                headers: {
                    'Content-Type': 'application/json',
                    'Client-ID': TWITCH_ID,
                    'Authorization': 'Bearer ' + data.access_token
                }
            });
    
            const newData = await response.json();
            console.log(newdata);
    
            if (!newdata.data) {
                return [];
            }
            return newdata.data.map(views => ({
                view_count: views.view_count
            }));
        }
    }