academind / yt-graphql-react-event-booking-api

Code for GraphQL + React Event Booking API Series: https://academind.com/learn/node-js/graphql-with-node-react-full-app/
395 stars 302 forks source link

Hooks version of fetching events upon mounting is not working after adding an event in Events.js #15

Closed adhupraba closed 4 years ago

adhupraba commented 4 years ago

I used state variable added to re-render the useEffect upon adding an event. The data is added to db but the app crashes. But when i remove the useEffect the data is added to db and and is getting logged in the console. Some please help me with the code below. I've been stuck in this for two days.

import React, { Fragment, useState, useRef, useContext, useEffect } from 'react'
import Backdrop from '../backdrop/Backdrop'
import Modal from '../Modal/Modal'
import AuthContext from '../context/authContext/authContext'
import axios from 'axios'

const Events = () => {

    const [creating, setCreating] = useState(false)
    const [events, setEvents] = useState([])
    const [added, setAdded] = useState(true)

    const authContext = useContext(AuthContext)

    const titleEl = useRef(null)
    const descEl = useRef(null)
    const priceEl = useRef(null)
    const dateEl = useRef(null)

    useEffect(() => {
        const fetchEvents = async () => {   
            try {

                console.log('inside fetchEvents()')
                const config = {
                    headers: {
                        'Content-Type': 'application/json'
                    }
                }

                const requestBody = {
                    query: `
                        query {
                            events {
                                _id
                                title
                                description
                                price
                            }
                        }
                    `
                }

                const body = JSON.stringify(requestBody)

                console.log('awaiting for events from db')

                const res = await axios.post('http://localhost:5000/graphql', body, config)

                console.log('events fetched from db')

                if (res.status !== 200 && res.status !== 201) {
                    throw new Error('Failed!')
                }

                console.log(res.data)
                setEvents(res.data.data.events)
            }
            catch(err) {
                console.log(err)
            }
        }

        if (added) {
            fetchEvents()
            setAdded(false)
        }

        fetchEvents()

    }, [added])

    const handleCreateEvent = () => {
        setCreating(true)
    }

    const handleCancel = () => {
        setCreating(false)
    }

    const handleConfirm =  () => {

            setCreating(false)
            const title = titleEl.current.value
            const desc = descEl.current.value
            // converts price to number
            const price = +priceEl.current.value
            const date = dateEl.current.value

            if (title.trim().length === 0 || desc.trim().length === 0 || price < 0 || date.trim().length === 0) {
                return
            }

            // request to backend
            const config = {
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${authContext.token}`
                }
            }

            const requestBody = {
                query: `
                    mutation {
                        createEvent(title: "${title}", description: "${desc}", price: ${price}, date: "${date}") {
                            _id
                            title
                            description
                            price
                        }
                    }
                `
            }

            const body = JSON.stringify(requestBody)

            console.log('adding to db')
            // const res = await axios.post('http://localhost:5000/graphql', body, config)
            axios.post('http://localhost:5000/graphql', body, config).then((res) => {
                console.log('added to db')
                if (res.status !== 200 && res.status !== 201) {
                    throw new Error('Failed!')
                }
                console.log(res.data)
                setAdded(true)
            })
    }

    const eventsList = events.map((event) => {
        return <li key={event._id} className='events__list-item'>{event.title}</li>
    })

    return (
        <Fragment>
            { creating && <Backdrop /> }
            {
                creating && (
                    <Modal title='Add Event' canCancel canConfirm onCancel={handleCancel} onConfirm={handleConfirm}>
                        <form>
                            <div className='form-control'>
                                <label htmlFor="title">Title</label>
                                <input ref={titleEl} type="text" id='title' />
                            </div>
                            <div className='form-control'>
                                <label htmlFor="description">Description</label>
                                <textarea ref={descEl} id='description' rows='4' />
                            </div>
                            <div className='form-control'>
                                <label htmlFor="price">Price</label>
                                <input ref={priceEl} type="number" id='price' />
                            </div>
                            <div className='form-control'>
                                <label htmlFor="date">Date</label>
                                <input ref={dateEl} type="datetime-local" id='date' />
                            </div>
                        </form>
                    </Modal>
                )
            }
            {
                authContext.token ? (
                    <div className='events-control'>
                        <p>Share your own events</p>
                        <button className='btn' onClick={handleCreateEvent}>Create Event</button>
                    </div>
                ) : (<h1>Login to Create Events</h1>)
            }
            <ul className="events__list">
               {eventsList}
            </ul>
        </Fragment>
    )
}

export default Events