Где я могу разместить эти реагирующие крючки? - PullRequest
0 голосов
/ 29 апреля 2020

У меня было несколько хуков, которые я использовал при рендеринге кода ниже - и они работали, пока я не добавил несколько useEffects. Я не знаю, куда поместить эти хуки, чтобы они снова заработали - теперь я получаю ошибку «рендеринг больше хуков, чем в прошлый раз» -

Хуки, которые я пытаюсь использовать, это FormatDate и BandIcon. FormatDate получает данные из props.post, а BandIcon получает данные из props.band. Можете ли вы помочь мне выяснить, куда поместить эти хуки, чтобы они снова работали?

Я попытался использовать их в первом useEffect, вызвав хук, чтобы установить новую часть состояния для хранения этого значения ... но это тоже не работал.

    import React, { useState, useEffect } from 'react'
import { Card, CardTitle, Badge, Button, CardFooter } from 'reactstrap'
import BandIcon from '../../../../uitls/BandIcon'
import FormatDate from '../../../../uitls/FormatDate'
import { Modal, ModalBody } from 'reactstrap'
import ReactMapGL, { Marker } from 'react-map-gl';
import { useAuth0 } from "../../../../react-auth0-spa";


let shouldUpdate = 0
let shouldUpdateStatus = 0
let shouldUpdateFavorites = 0

export default function ShowsPosts(props) {
    const { user } = useAuth0();
    const { post, band, _id, addRockOn, addFavorites, favorites } = props
    const [ day, setDay ] = useState('')
    const [ client, setClient ] = useState()
    const [ approved, setApproved ] = useState('')
    const [customQuotes, setCustomQuotes] = useState([])
    const [modal, setModal] = useState(false);
    const [ perfromanceDate, setPerformanceDate ] = useState('')
    const [ venueAddress, setVenueAddress ] = useState([])
    const [ viewPort, setViewport ] = useState();
    const [ total, setTotal ] = useState(0);
    const [ baseCost, setBaseCost ] = useState(0);
    const { getTokenSilently } = useAuth0();
    const [isUser, setIsUser ] = useState(null)
    const [ rocks, setRocks ] = useState([])
    const [ renderIcon, setRenderIcon ] = useState('')

    useEffect(() => {
        //Required Gig Details
        post.details.map(detail => {
            if(detail.title === "Performance Date"){
                setPerformanceDate(detail.detail)
            }

            if(detail.title === "Venue Address"){
                setVenueAddress(detail.detail)
            }

            if(detail.title === 'Base Cost'){
                setBaseCost(detail.money)
            }
            return null
        })

        //Client
        setClient(post.client)

        let slicedDay = new Date(post.details.map(detail => {
            if (detail.title === "Performance Date"){
                return detail.detail
            }else{
                return null
            }
        })).toDateString().slice(0,3)

        //Create Day Icon
        switch (slicedDay){
            case 'Mon':
                setDay('monday.svg')
                break;
            case 'Tue':
                setDay('tuesday.svg')
                break;
            case 'Wed':
                setDay('wednesday.svg')
                break;
            case 'Thu':
                setDay('thursday.svg')
                break;
            case 'Fri':
                setDay('friday.svg')
                break;
            case 'Sat':
                setDay('saturday.svg')
                break;
            default:
                console.log('switch didnt work')
        }   

        //Gig Status
        setApproved(post.approved)

        //Add Custom Qutoes - I added the return in the first part
        post.details.filter(detail => {
            if(detail.title !== "Performance Date" || detail.title !== "Base Cost" || detail.title !== "Venue Address"){
                return setCustomQuotes(quotes => [...quotes, detail])
            }else {
                return null
            }
        })

        //Set Total
        setTotal(post.total)

        setRocks(post.rockOn)

    }, [post])

    useEffect(() => {
        if(shouldUpdate >= 1){
            setViewport({
                latitude: post.details.filter(detail => {
                    if(detail.title === "Venue Address"){
                        return detail.detail[2][1]
                    }else {
                        return null
                    }
                })[0].detail[2][0] ,
                longitude: post.details.filter(detail => {
                    if(detail.title === "Venue Address"){
                        return detail.detail[2][1]
                    }else {
                        return null
                    }
                })[0].detail[2][1],
                width: '100%',
                height: 100,
                zoom: 12,
            })
        }else {
            shouldUpdate += 1
        }
    }, [venueAddress, post.details])

    const saveBookingStatus = async (newStatus) => {
        const token = await getTokenSilently();

        try {
            await fetch(`/api/autoquotegenerators/posts/${_id}/${post.postId}`, {
                method: 'PUT',
                headers: {
                    "Content-Type": "application/json; charset=UTF-8",
                    Authorization: `bearer ${token}`
                },
                body: JSON.stringify(
                    {
                        "approved": newStatus
                    }
                )
            })
        } catch (error) {
            console.log(error)
        }

    }

    useEffect(() => {
        if(user.sub.slice(6, user.sub.length) === band.userId){
            setIsUser(true)
        }else{
            setIsUser(false)
        }

    }, [band, user])

    const toggle = () => setModal(!modal);


    if( !post || !band || !user || !rocks || !approved ){
        console.log(post)
        console.log(band)
        console.log(user)
        console.log(rocks)
        console.log(approved)
        return <div>...loading</div>
    }

    const handleRockOn = () => {
        if(rocks.includes(user.sub.slice(6, user.sub.length))){
            setRocks(rocks => [...rocks.filter(rock => { return rock !== user.sub.slice(6, user.sub.length)})])
            addRockOn(post.postId, rocks.filter(rock => { return rock !== user.sub.slice(6, user.sub.length)}), props._id)
        }else {
            setRocks(rocks => [...rocks, user.sub.slice(6, user.sub.length)])
            addRockOn(post.postId, rocks.concat(user.sub.slice(6, user.sub.length)), props._id)
        }
    }

    const handleFavorites = () => {
        addFavorites(user.sub.slice(6, user.sub.length), band)
    }

    return (
        <Card  color="light" className="my-1 d-flex flex-column justify-content-start">
            <span className="d-flex flex-row align-self-start mx-2 mt-2 mb-1">
                <img onClick={()=> {window.location.href=`/band/${_id}`}} src={BandIcon(band.bandGenre)} alt="Band Icon" style={{
                    width: "30px",
                    height: "30px",
                    cursor: 'pointer'
                }}/>
                <span className="h6 mt-2 mx-1">
                    <strong onClick={()=> {window.location.href=`/band/${_id}`}} style={{cursor: 'pointer'}}>{band.bandName}</strong> - {FormatDate(post.date)}
                </span>
            </span>

            <Button 
            color="light" 
            id="dateCardPost"
            onClick={toggle} 
            className="d-flex flex-row align-self-start p-4 mx-5 mt-1 mb-3 w-75" 
            style={{cursor: "pointer",
                    pointerEvents: isUser ? "auto" : "none" }}
            >

                <img src={`/calendarIcons/${day}`} 
                className="mr-2" 
                alt=""
                style={{
                    width: "85px",
                    height: "85px",
                }}/>
                <Badge color="primary" className="align-self-start mx-1 mt-1" style={{
                    display: approved === 'pending' ? "block" : "none"
                }}>?</Badge>
                <Badge color="danger" className="align-self-start mx-1 mt-1" style={{
                    display: approved === 'false' ? "block" : "none"
                }}>X</Badge>
                <Badge color="success" className="align-self-start mx-1 mt-1" style={{
                    display: approved === 'true' ? "block" : "none"
                }}>✓</Badge>       
                <CardTitle className="d-flex flex-column mx-1 align-items-start">

                    <span><strong>{band.bandName}'s</strong> Show</span>

                    <span>on <strong>{perfromanceDate.slice(4)}</strong></span>

                    <span>at <strong>{venueAddress[1]} </strong></span>
                    <span>
                    is {approved === 'pending' ? 'un-confirmed!' : null}
                    {approved === 'false' ? 'cancelled!' : null}
                    {approved === 'true' ? 'confirmed!' : null}
                    </span>

                </CardTitle>

            </Button>
            <Modal isOpen={modal} toggle={toggle}>
                <ReactMapGL 
                        style={{zIndex: "2"}}
                        {...viewPort} 
                        mapboxApiAccessToken={"pk.eyJ1Ijoibmlja2lzeW91cmZhbiIsImEiOiJjazh5azhjNjUxNzIwM21zZmdoZTBoM243In0.4ijWndTzChYeKo67PYSuAw"}
                        onViewportChange={viewport => setViewport(viewport)}
                        mapStyle="mapbox://styles/nickisyourfan/ck8ylgfk90kcb1iqoemkes76u"
                        >

                            <Marker 
                            latitude={post.details.filter(detail => {
                                if(detail.title === "Venue Address"){
                                    return detail.detail[2][1]
                                }else {
                                    return null
                                }
                            })[0].detail[2][0]} 
                            longitude={post.details.filter(detail => {
                                if(detail.title === "Venue Address"){
                                    return detail.detail[2][1]
                                }else {
                                    return null
                                }
                            })[0].detail[2][1]} 
                            offsetLeft={-25}
                            offsetTop={-20}>
                                <img src={BandIcon(band.bandGenre)} alt="Band Icon" style={{
                                width: "30px",
                                height: "30px",
                                }}/>
                            </Marker>
                        </ReactMapGL>
                <ModalBody className="d-flex flex-column align-items-start">
                    <Card color="light" className="d-flex flex-column py-3 w-75 align-self-center justify-content-center align-items-center h5">{band.bandName}</Card>
                    <Card color="light" className="d-flex flex-column py-2 w-75 align-self-center justify-content-center align-items-center h6">
                        <span className="h6">{perfromanceDate}</span>
                        <span><strong>Venue: </strong>{venueAddress[1]}</span>
                        <span><strong>Address: </strong>{venueAddress[0]}</span>
                    </Card>
                    <Card color="light" className="d-flex flex-column py-2 w-75 align-self-center justify-content-center align-items-center h6">
                        <span><strong>Client: </strong>{client}</span>

                        <span><strong>Base Cost: </strong>${baseCost}</span>
                        {customQuotes.map(quote => {
                            if(quote.title !== 'Venue Address' || quote.title !== 'Base Cost' || quote.title !== 'Performance Date'){
                                return null
                            }else {
                                return <span key={quote.chargeId}><strong>{quote.title}: </strong>{quote.detail} ${quote.money}</span>
                            }
                        })}

                    </Card>
                    <Card color="light" className="d-flex flex-column py-2 w-75 align-self-center justify-content-center align-items-center h6">
                        <span><strong>Total: </strong>${total}</span>
                    </Card>
                </ModalBody>
                <Button 
                id="cancelBookingButton"
                onMouseEnter={() => { 
                    if(approved === 'true'){
                        document.getElementById('cancelBookingButton').innerHTML = 'Cancel Booking?'}
                }}
                onMouseLeave={() => {
                    if(approved === 'true'){
                        document.getElementById('cancelBookingButton').innerHTML = 'Booking Approved'
                    }
                }}
                onClick={() => {
                    setApproved('false') 
                    saveBookingStatus('false')
                }} 
                className="w-100 rounded-0" 
                color={approved === 'pending' ? 'danger' : 'success'} 
                style={{
                display: approved === 'pending' || approved === 'true' ? 'block' : 'none',
                }}>
                    {approved === 'pending' ? 'Decline Booking' : 'Booking Approved'}
                </Button>
                <Button 
                id="approveBookingButton"
                onMouseEnter={() => {
                    if(approved === 'false'){
                        document.getElementById('approveBookingButton').innerHTML = 'Re-Confirm Booking?'
                    }
                }}
                onMouseLeave={() => {
                    if(approved === 'false'){
                        document.getElementById('approveBookingButton').innerHTML = 'Booking Cancelled'
                    }
                }}
                onClick={() => {
                    setApproved('approved')
                    saveBookingStatus('approved')
                }} 
                className="w-100 rounded-0" 
                color={approved === 'false' ? 'danger' : 'success'} 
                style={{
                    display: approved === 'false' || approved === 'pending' ? 'block' : 'none',
                }}>
                    {approved === 'pending' ? 'Approve Booking' : 'Booking Cancelled'}
                </Button>
            </Modal>
            <CardFooter className="d-flex flex-row justfiy-content-between p-0">
                <Button onClick={handleRockOn} color={rocks.includes(user.sub.slice(6, user.sub.length)) ? 'light active' : 'light'} className="d-flex w-50 h-100 rounded-0 justify-content-center shadow-none" >
                    <img src='/Rock-On.svg' style={{width: '27px', height: '27px'}} className="mr-2"/>
                    <span className="ml-2">{rocks.length}</span>
                </Button>
                <Button onClick={handleFavorites} color={favorites.includes(user.sub.slice(6, user.sub.length)) ? 'light active' : 'light'} className='w-50 h-100 rounded-0' style={{boxShadow: 'none'}}>
                    <img src='/FavoriteBand.svg' style={{width: '25px', height: '25px'}} />
                </Button>
            </CardFooter>
        </Card>
    )
}

1 Ответ

0 голосов
/ 29 апреля 2020

Кажется, у вас много логик c внутри одного компонента. Я предлагаю начать с разделения частей связанных логик c на отдельные хуки, чтобы у вас было меньше кода внутри ваших компонентов и вы могли бы найти, где находятся ошибки при их извлечении.

Пример реализации :

function useViewport(venueAddress, postDetails) {
    const [viewPort, setViewport] = useState();
    useEffect(() => {

      if (shouldUpdate >= 1) {
        setViewport({
          latitude: post.details.filter((detail) => {
            if (detail.title === 'Venue Address') {
              return detail.detail[2][1];
            } else {
              return null;
            }
          })[0].detail[2][0],
          longitude: post.details.filter((detail) => {
            if (detail.title === 'Venue Address') {
              return detail.detail[2][1];
            } else {
              return null;
            }
          })[0].detail[2][1],
          width: '100%',
          height: 100,
          zoom: 12,
        });
      } else {
        shouldUpdate += 1;
      }
    }, [venueAddress, postDetails]);

    return viewPort;
  } 

Внутри вашего ShowsPosts компонента:

useViewport(venueAddress, post.details);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...