Отправить компонент новые реквизиты реагируют - Stuck - PullRequest
1 голос
/ 28 апреля 2020

Я застрял на несколько часов сейчас .. Я пытаюсь отправить компоненту новые реквизиты ... но он не получит новые.

Вот что происходит.

Сначала пользователь нажимает кнопку на компоненте публикации ... Он запускает функции «добавить избранное» и «addFavs» в родительском компоненте ниже. Эти две функции определяют, следует ли добавить пользователя в избранное или удалить пользователя из избранного.

Когда пользователь добавляется в избранное, кнопка, которую он щелкнул внутри компонента searchResults, отображается другим цветом. Проблема в том, что они должны дважды щелкнуть кнопку, чтобы новые реквизиты были отправлены обратно в компонент searchResults, и изменить цвет - и я не могу понять, как получить useEffect для отправки компоненту новых реквизитов.

Внутри функции 'addFavs' я вызываю функции оригинального поиска 'getBands' и 'getTourBands', чтобы получить обновленные данные. Это добавляется к состояниям, называемым полосами, всеми полосами и турами. Моя теория заключалась в том, что как только эти обновленные данные будут добавлены в состояние, они отправят новые реквизиты моему searchResultsComponent.

Спасибо за вашу помощь - дайте мне знать, если это слишком сложно.

    import React, { useState, useEffect } from 'react'
import { Button, Card, CardTitle } from 'reactstrap'
import LocationInput from './LocationInput'
import TypeInput from './TypeInput'
import VideosInput from './VideosInput'
import ShowsInput from './ShowsInput'
import VideoPosts from '../../SetupCards/Posts/Views/VideoPosts'
import ShowsPosts from '../../SetupCards/Posts/Views/ShowsPosts'
import FeedPosts from '../../SetupCards/Posts/Views/FeedPosts'
import { useAuth0 } from "../../../react-auth0-spa";
import BandCard from '../../BookABand/BandCard'
import SearchResults from './SearchResults'

let shouldUpdate = 0

export default function BandSearchBar(props) {
    const [ isSelected, setIsSelected ] = useState('location')
    const [ bands, setBands ] = useState([])
    const [ tourBands, setTourBands ] = useState([])
    const [ allBands, setAllBands ] = useState([])
    const [ locationText, setLocationText ] = useState('')
    const [ location, setLocation ] = useState([])
    const [ genre, setGenre ] = useState('Genre/Style')
    const [ bandTypes, setBandTypes ] = useState('all')
    const [ videosFilter, setVideosFilter ] = useState('all')
    const [ showsFiltered, setShowsFiltered ] = useState('all')
    const { getTokenSilently } = useAuth0();
    const { loading, user } = useAuth0();

    const getHomeBands = async () => {
        const token = await getTokenSilently();
        try {
            const response = await fetch(`/api/autoquotegenerators/homeBands/${location[0]}/${location[1]}`, {
                headers: {
                    Authorization: `Bearer ${token}`,
                }
            })
            const responseData = await response.json();
            if(responseData !== []){
                setBands(responseData)
            }
        } catch (error) {
            console.log(error)
        }
    }
    const getTourBands = async () => {
        const token = await getTokenSilently();
        try {
            const response = await fetch(`/api/autoquotegenerators/tourBands/${location[0]}/${location[1]}`, {
                headers: {
                    Authorization: `Bearer ${token}`,
                }
            })
            const responseData = await response.json();
            if(responseData !== []){
                setTourBands(responseData)
            }
        } catch (error) {
            console.log(error)
        }
        let allBandsArray = Array.from(bands).concat(tourBands)
            setAllBands(allBandsArray)
    }

    useEffect(() => {
        setTimeout(() => {
            if(shouldUpdate >= 1){
                getHomeBands()
                getTourBands()
            }else {
                shouldUpdate += 1
            }

        },250)
    }, [location])

    const searchLocation = (location, text) => {
        setLocation(location)
        setLocationText(text)
    }

    const showCard = (set) => {
        switch(set){
            case 'location':
                return <div><LocationInput savedLocationText={locationText} searchLocation={searchLocation} savedGenre={genre} filterByGenre={filterByGenre} /></div>
            case 'bands':
                return <div><TypeInput savedType={bandTypes} filterBandTypes={filterBandTypes} /> </div>
            case 'videos':
                return <div><VideosInput filterByVideos={filterByVideos} videosFilter={videosFilter} /> </div>
            case 'shows':
                return <div><ShowsInput filterShows={filterShows} showsFiltered={showsFiltered}/> </div>
        }
    }

    if (loading || !user) {
        return <div>Loading...</div>;
    }

    const addRockOn = async (postId, rocks, _id) => {
        const token = await getTokenSilently();
        try {
            await fetch(`/api/autoquotegenerators/posts/${_id}/${postId}`,{
                method: 'PUT',
                headers: {
                    Authorization: `Bearer ${token}`,
                    "Content-Type": "application/json; charset=UTF-8",
                },
                body: JSON.stringify({
                    rockOn: rocks
                })
            })
        } catch (error) {
            console.log(error)
        }
    }

    const addFavorites = (userId, band) => {

        if(band.favorites.includes(userId)){
            addFavs(band.favorites.filter(fav => {
                return fav !== userId
            }), band._id)

        }else {
            addFavs(band.favorites.concat(userId), band._id)
        }

    }

    const addFavs = async (favs, id) => {
        const token = await getTokenSilently();
            try{
                await fetch(`/api/autoquotegenerators/${id}`, {
                    method: 'PUT',
                    headers: {
                        Authorization: `Bearer ${token}`,
                        "Content-Type": "application/json; charset=UTF-8",
                    },
                    body: JSON.stringify({
                        favorites: favs
                    })
                })
                getHomeBands()
                getTourBands()
            } catch(error){
                console.log(error)
            }
    }

    const convertPost = (post, band) => {
        if(genre === 'Genre/Style'){
            switch (post.type) {
                case "video":
                    return (
                        <VideoPosts addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} link={post.data} band={band} post={post} _id={band._id} />
                    )
                case "text":
                    return (
                        <FeedPosts addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} band={band}  post={post} _id={band._id}/>
                    )   
                case "show":
                    return (
                        <ShowsPosts addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} band={band} post={post} _id={band._id}/>
                    )
                default: 
                    return null;
            }
        }else {
            if(band.bandGenre === genre ){
                switch (post.type) {
                    case "video":
                        return (
                            <VideoPosts addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} link={post.data} band={band} post={post} />
                        )
                    case "text":
                        return (
                            <FeedPosts addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} band={band} post={post} _id={band._id} />
                        )   
                    case "show":
                        return (
                            <ShowsPosts addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} band={band} post={post} _id={band._id}/>
                        )
                    default: 
                        return null;
                }
            }
        }

    }

    const convertBand = (band) => {
        if(genre === 'Genre/Style'){
            return <Button color="light" className="w-100 mb-1">
            <BandCard id={band._id} key={band.bandName} youtube={band.youtube} bandName={band.bandName} bandBio={band.bandBio} />
            </Button>
        }else {
            if(band.bandGenre === genre){
                return <Button color="light" className="w-100 mb-1">
                <BandCard id={band._id} key={band.bandName} youtube={band.youtube} bandName={band.bandName} bandBio={band.bandBio} />
                </Button> 
            }
        }
    }

    const createPromoVideo = (link, band) => {
        let post = {
            date: null
        }
        return <VideoPosts post={post} link={link} band={band} _id={band._id} />
    }

    const filterBandTypes = (type) => {
        setBandTypes(type)
    }

    const filterByGenre = (genre) => {
        setGenre(genre)
    }

    const filterByVideos = (videos) => {
        setVideosFilter(videos)
    }

    const filterShows = (shows) => {
        setShowsFiltered(shows)
    }

    return (
        <div className="d-flex flex-column">
            <div className="d-flex flex-row">
                <Button id="location" onClick={() => {setIsSelected('location')}} 
                color={isSelected === 'location' ? "dark active" : "dark"} className="w-100 h5" style={{borderTopLeftRadius: '3px', borderBottomLeftRadius: '3px', borderTopRightRadius: '0px', borderBottomRightRadius: '0px'}} >Feed</Button>
                <Button id="bands" onClick={() => {setIsSelected('bands')}} color={isSelected === 'bands' ? "dark active" : "dark"}  className="w-100 h5 rounded-0">Bands</Button>
                <Button id="videos" onClick={() => {setIsSelected('videos')}} 
                color={isSelected === 'videos' ? "dark active" : "dark"} className="w-100 h5 rounded-0">Videos</Button>
                <Button id="shows" onClick={() => {setIsSelected('shows')}}  color={isSelected === 'shows' ? "dark active" : "dark"} className="w-100 h5" style={{borderTopRightRadius: '3px', borderBottomRightRadius: '3px', borderTopLeftRadius: '0px', borderBottomLeftRadius: '0px'}}>Shows</Button>
            </div>
            <div>
                {isSelected ? showCard(isSelected) : null}
            </div>
            <SearchResults isSelected={isSelected} bandTypes={bandTypes} allBands={allBands} bands={bands} tourBands={tourBands} convertPost={convertPost} convertBand={convertBand} videosFilter={videosFilter} showsFiltered={showsFiltered} createPromoVideo={createPromoVideo}/>
        </div>
    )
}

Я также пытался использовать хук useEffect () для вызова функции для отображения компонента с новыми реквизитами. Еще ничего. ** Когда я попробовал использовать эффект, я прослушал «группы», «allBands» и «tourBands». Если бы они изменились, он передал бы компонент в функцию, которая отображала бы его в рендере - это не сработало, поэтому я не включил его в мой код выше.

Вот файл / компонент SearchRestuls. js

        import React from 'react'

    export default function SearchResults(props) {
    const {isSelected, bandTypes, allBands, bands, tourBands, convertPost, convertBand, videosFilter, showsFiltered, createPromoVideo} = props

    return (
    <div>
    <div style={{
        display: isSelected === 'location' ? 'block' : 'none'
    }}>

        {bandTypes === 'all' ? allBands.map(band => {
            return band.posts.map(post => {
                let currPost = convertPost(post, band)
                return currPost
            })
        }).reverse() : null}

        {bandTypes === 'local' ? bands.map(band => {
            return band.posts.map(post => {
                let currPost = convertPost(post, band)
                return currPost
            })
        }).reverse() : null}

        {bandTypes === 'touring' ? tourBands.map(band => {
            return band.posts.map(post => {
                let currPost = convertPost(post, band)
                return currPost
            })
        }).reverse() : null}

    </div>
    <div style={{
        display: isSelected === 'bands' ? 'block' : 'none'
    }}>
        {bandTypes === 'all' ? allBands.map(band => {
            let currBand = convertBand(band)
            return currBand
        }) : null}
        {bandTypes === 'local' ? bands.map(band => {
            let currBand = convertBand(band)
            return currBand
        }) : null}
        {bandTypes === 'touring' ? tourBands.map(band => {
            let currBand = convertBand(band)
            return currBand
        }) : null}
    </div>
    <div style={{
        display: isSelected === 'videos' ? 'block' : 'none'
    }}>
        {bandTypes === 'all' && videosFilter === 'all' ? allBands.map((band) => {
            return band.posts.map(post => {
                if(post.type === 'video'){
                    let currBand = convertPost(post, band)
                    return currBand
                }
            })
        }) : null}
        {bandTypes === 'local' && videosFilter === 'all' ? bands.map((band) => {
            return band.posts.map(post => {
                if(post.type === 'video'){
                    let currBand = convertPost(post, band)
                    return currBand
                }
            })
        }) : null}
        {bandTypes === 'touring' && videosFilter === 'all' ? tourBands.map((band) => {
            return band.posts.map(post => {
                if(post.type === 'video'){
                    let currBand = convertPost(post, band)
                    return currBand
                }
            })
        }) : null}

        {bandTypes === 'all' && videosFilter === 'promo' ? allBands.map((band) => {
            return band.youtube.map(link => {
                let currVid = createPromoVideo(link, band)
                return currVid
            })
        }) : null}
    </div>
    <div style={{
        display: isSelected === 'shows' ? 'block' : 'none'
    }}>
        {bandTypes === 'all' && showsFiltered === 'all' ? allBands.map((band) => {
            return band.posts.map(post => {
                if(post.type === 'show'){
                    let currBand = convertPost(post, band)
                    return currBand
                }
            })
        }) : null}
        {bandTypes === 'local' && showsFiltered === 'all' ? bands.map((band) => {
            return band.posts.map(post => {
                if(post.type === 'show'){
                    let currBand = convertPost(post, band)
                    return currBand
                }
            })
        }) : null}
        {bandTypes === 'touring' && showsFiltered === 'all' ? tourBands.map((band) => {
            return band.posts.map(post => {
                if(post.type === 'show'){
                    let currBand = convertPost(post, band)
                    return currBand
                }
            })
        }) : null}

        {bandTypes === 'all' && showsFiltered === 'upcoming' ? allBands.map((band) => {
            return band.posts.map(post => {
                if(post.type === 'show'){
                    let performanceDateUnformatted;
                    performanceDateUnformatted = post.details.filter(detail => {
                        if(detail.title === 'Performance Date'){
                            return detail.detail
                        }
                    })[0].detail

                    var months = {
                        'Jan' : '01',
                        'Feb' : '02',
                        'Mar' : '03',
                        'Apr' : '04',
                        'May' : '05',
                        'Jun' : '06',
                        'Jul' : '07',
                        'Aug' : '08',
                        'Sep' : '09',
                        'Oct' : '10',
                        'Nov' : '11',
                        'Dec' : '12'
                    }

                    let year = performanceDateUnformatted.slice(11)
                    let day = performanceDateUnformatted.slice(8,10)
                    let month = months[performanceDateUnformatted.slice(4,7)]

                    let showDateFormatted = new Date(year, month - 1, day)

                    let today = new Date()

                    let todayPlusOneWeek = new Date(today.getUTCFullYear(), today.getUTCMonth(), today.getDate() + 7)

                    if(showDateFormatted > today && showDateFormatted < todayPlusOneWeek ){
                        let currBand = convertPost(post, band)
                        return currBand
                    }else {
                        return null
                    }
                }
            })
        }) : null}
    </div>
    </div>
    )
    }

Ответы [ 2 ]

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

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

Я полагаю, что проблема вызвана тем, что getHomeBands и getTourBands являются отдельными функциями и setAllBands в getTourBands, полагаясь на bands, которые были изменены в getHomeBands. React не обещает, что состояние будет актуальным, если вы вызовете несколько изменений очень быстро, и здесь они могут произойти почти одновременно. Кроме того, вы выполняете сетевые выборки, которые могут заканчиваться sh в другом порядке, нежели вы их вызывали, а это означает, что новый bands, возможно, даже не прибыл.

Чтобы это исправить, просто объедините 2 функции и вызывают все 3 setStates с данными, которые не зависят от текущего состояния.

    const getBands = async () => {
        const token = await getTokenSilently();
        try {
            let response = await fetch(`/api/autoquotegenerators/homeBands/${location[0]}/${location[1]}`, {
                headers: {
                    Authorization: `Bearer ${token}`,
                }
            })
            const newBands = await response.json();
            if(newBands !== []){
                setBands(newBands)
            }

            response = await fetch(`/api/autoquotegenerators/tourBands/${location[0]}/${location[1]}`, {
                headers: {
                    Authorization: `Bearer ${token}`,
                }
            })
            const newTourBands = await response.json();
            if(newTourBands !== []){
                setTourBands(newTourBands)
            }

            if((newBands !== []) && (newTourBands !== [])){
                setAllBands([ ...newBands, ...tourBands])
            }
        } catch (error) {
            console.log(error)
        }
    }
0 голосов
/ 29 апреля 2020

Я не очень знаком с async / await в реакции, но, возможно, есть проблема с ним? Ваш код кажется правильным, но, например, действительно ли это условие иногда действительно?

const responseData = await response.json();
if (responseData !== []) {
  setTourBands(responseData);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...