I have a site that is rendering cards of music artists then allowing the user to click on a button "View Ticket Activity" on each artist's card, which then allows more information to show up. Styled using Tailwind (the class names) and using react-router-v6.
I defined my artists state to successfully pull all the seeded artists from a rails DB and I output these artists all at once via a component called <ArtistsDisplay /> (which is routed to '/artists', where I pass down artists={artists} from the parent component <App />. In <ArtistsDisplay />, each artist maps out.
I have a separate component called <EachArtistCard /> that is routed (in <App />) to '/artists/:id' and is redirected there by a useNavigate() within <ArtistDisplay />. The problem there is that artist passes down from the parent <ArtistDisplay /> to the child <EachArtistCard /> and thisArtist=undefined on the first pass, which then breaks the map function within <EachArtistCard />. I'm defining it as thisArtist in place of artist within as a just in case to not have conflict name-wise with the const thisArtist = artists.find( (artist) => parseInt(id) === parseInt(artist.id) );
Within <ArtistsDisplay /> is my major issue. I've tried many re-writes (replacing the new component with an in-component modal, reconfiguring routes, etc) but fundamentally I need to understand why I have the thisArtist=undefined rendering issue. I'm not in strictMode (afaik) as I've seen the double-render-in-development posts so it's gotta be my error somewhere in my writing of this app.
ArtistsDisplay.js
function ArtistsDisplay({ artists, user, searchTerm, setSearchTerm }) {
let navigate = useNavigate();
return (
<div class='bg-base-900 py-6 sm:py-8 lg:py-12'>
<div class='form-control'>
<label class='flex input-group input-group-lg'>
<span>SEARCH</span>
<input
type='text'
onChange={(e) => setSearchTerm(e.target.value)}
placeholder='Search for your favorite artists here...just start typing'
class='input input-bordered w-full input-lg text-center'
/>
</label>
</div>
<div>
<div class='mx-auto max-w-screen-xl px-4 md:px-8'>
<div class='mb-10 md:mb-16'>
<h1 class='mb-4 text-center text-6xl font-thin text-primary md:mb-6 lg:text-7xl'>
ARTISTS
</h1>
<p class='mx-auto uppercase text-center max-w-screen-md text-secondary text-gray-500 md:text-lg'></p>
</div>
<div class='grid gap-8 mx-6 sm:grid-cols-2 sm:gap-12 lg:grid-cols-3 '>
{artists
.filter((artist) => {
if (searchTerm === '') {
return artist;
} else if (
artist.name.toLowerCase().includes(searchTerm.toLowerCase())
) {
return artist;
}
})
.map((artist) => (
<div>
<div
key={artist.id}
class='card w-96 max-w-xs bg-neutral text-neutral-content shadow-xl'>
<div class='card-body p-4 m-2 mx-0 items-center text-center'>
<div class='avatar'>
<div class='w-30 rounded'>
<img
src={artist.image}
alt='a small avatar of the musical artist'
/>
</div>
</div>
<h1 class='card-title'>{artist.name}</h1>
<p>{artist.genre.name}</p>
<div class='card-actions justify-end'>
<button
class='btn btn-primary'
onClick={() => navigate(`/artists/${artist.id}`)}>
view ticket activity
</button>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
}
export default ArtistsDisplay;
EachArtistCard.js
note: even with the two useEffects below commented out, thisArtist still =undefined
import React from 'react';
import { useParams } from 'react-router-dom';
import { useEffect, useState } from 'react';
import IndividualPost from './IndividualPost';
function EachArtistCard({ posts, setPosts, artists }) {
let { id } = useParams();
const thisArtist = artists.find(
(artist) => parseInt(id) === parseInt(artist.id)
);
//* to set selling & looking
useEffect(() => {
thisArtist.posts.map((each) => {
if (each.for_sale === true) {
setSelling(selling + 1);
} else {
setLooking(looking + 1);
}
});
}, []);
//* to set upcomingShows
useEffect(() => {
thisArtist.concerts.map((each) => setUpcomingShows(upcomingShows + 1));
}, []);
return (
<div>
<div class='bg-base-900 py-6 sm:py-8 lg:py-'>
<div class='mx-auto max-w-screen-xl px-4 md:px-8'>
<div class='mb-10 md:mb-16'>
<h1 class='mb-4 text-center text-6xl font-thin uppercase text-primary md:mb-6 lg:text-7xl'>
{thisArtist.name}
</h1>
</div>
<div class='flex justify-center'>
<div class='card w-96 bg-base-500 bg-neutral text-neutral-content justify-center shadow-2xl'>
<div class='avatar'>
<div class='w-30 rounded'>
<img
src={thisArtist.image}
alt='a small avatar of the music thisArtist'
/>
</div>
</div>
<div class='card-body items-center text-center'>
<h2 class='card-title'>{thisArtist.name}</h2>
<p>
There's {upcomingShows} upcoming concerts listed for{' '}
{thisArtist.name}!
</p>
<div>
<div class='badge badge-primary uppercase'>
{selling} selling
</div>
<div class='badge badge-primary uppercase'>
{looking} looking
</div>
</div>
<div class='card-actions justify-end'>
<button class='btn btn-secondary w-full'>
I have tickets to sell
</button>
<button class='btn btn-secondary w-full'>
I'm Looking For Tickets
</button>
<button class='btn btn-outline btn-black w-full'>
Go Back
</button>
</div>
</div>
</div>
</div>
<h2 class='my-10 text-center text-5xl font-thin uppercase text-primary md:mb-6 lg:text-6xl'>
ALL POSTS
</h2>
</div>
</div>
</div>
);
}
export default EachArtistCard;
App.js
removed a lot of other code not pertaining to the situation here
import '../../src/App.css';
import ArtistsDisplay from './ArtistsDisplay';
import ConcertsDisplay from './ConcertsDisplay';
import VenuesDisplay from './VenuesDisplay';
import GenreDisplay from './GenreDisplay';
import Login from './Login';
import SignUp from './SignUp';
import NotFound from './NotFound';
import Header from './Header';
import { Route, Routes } from 'react-router-dom';
import { useState, useEffect } from 'react';
import UsersPage from './UsersPage';
import EachArtistCard from './EachArtistCard';
function App() {
const [user, setUser] = useState('');
const [sessionInfo, setSessionInfo] = useState([]);
const [searchTerm, setSearchTerm] = useState('');
const [artists, setArtists] = useState([]);
useEffect(() => {
fetch('/artists')
.then((r) => r.json())
.then((info) => setArtists(info));
}, []);
return (
<div>
<Header
user={user}
setUser={setUser}
onLogin={onLogin}
onLogout={onLogout}
loggedIn={loggedIn}
/>
<Routes>
<Route
path='/'
element={
<UsersPage
user={user}
cookies={cookies}
sessionInfo={sessionInfo}
loggedIn={loggedIn}
/>
}
/>
<Route
path='/artists'
element={
<ArtistsDisplay
artists={artists}
genres={genres}
user={user}
posts={posts}
setPosts={setPosts}
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
showModal={showModal}
setShowModal={setShowModal}
/>
}
/>
<Route
path='/artists/:id'
element={
<EachArtistCard
artists={artists}
concerts={concerts}
posts={posts}
setPosts={setPosts}
user={user}
/>
}
/>
<Route path='*' element={<NotFound />} />
</Routes>
</div>
);
}
export default App;
Will take any steps in the right direction as I'm lost. If more info is needed, please let me know.