У меня было несколько хуков, которые я использовал при рендеринге кода ниже - и они работали, пока я не добавил несколько 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>
)
}