Manipulating state with useEffect, but not correctly rendering updated from updated state

I am building a new portfolio site out of a few new (to me) technologies and am running into an issue where I can set the initial state fine using useState React hook, but when I update the state, it is not rendering from the new state. I was attempting to use useEffect but have since removed it but I am beginning to think I am missing some core concept of implementation for this hooksand would appreciate any advice or recommended reading to help me over this hurdle. My code is as follows ( I apologize in advance for the terrible typescript, as that is one of the things I am attempting to learn, and appreciate any advice there as well):

index.tsx UPDATED

import Head from 'next/head'
import { useState } from 'react';
import Body from '../components/Body'
import HeaderItem from "../components/HeaderItem"
import {
    UserCircleIcon,
    CollectionIcon,
    BeakerIcon,
} from '@heroicons/react/outline'


type BodyProps = {
  image: string,
  text: string,
}

const Intro= {
  image: 'https://avatars.githubusercontent.com/u/2357717?v=4',
  text: 'Hello this is gonna be the new INTRO body! Hopefully using the body as a component will make single page transitions cleaner'
}

const Skills = {
  image: 'https://avatars.githubusercontent.com/u/2357717?v=4',
  text: 'Hello this is gonna be the new SKILL body! Hopefully using the body as a component will make single page transitions cleaner'
}


export default function Home({ image, text }: BodyProps) {
  const [ currentDisplay, setCurrentDisplay ] = useState(Intro);

  const handleClick = (display) => {
    setCurrentDisplay({
      image: display.image,
      text: display.text
    });
  }

  return (
    <div className="">
      <Head>
        <title>Eric Anderson</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      
      <header className='flex flex-col sm:flex-row m-5 justify-between items-center'>
        <h1 className="text-2xl pb-10">ERIC ANDERSON</h1>
        <div className='flex flex-row justify-evenly max-w-2xl'>
        
          <HeaderItem handleClick={() => handleClick(Intro)} Icon={UserCircleIcon} title='Intro' />

          <HeaderItem handleClick={() => handleClick(Skills)} Icon={BeakerIcon} title='Skills' />

          <HeaderItem  Icon={CollectionIcon} title='Github' />

        </div>
      </header> 
      {/* Header - Name github  Intro Skills */}
      <Body display={currentDisplay}/>
      {/* Body req: image=svg && text=string */}
    </div>
  )
}

components/Body.tsx UPDATED

type BodyProps = {
    image: string,
    text: string,
}

function Body({ display }: BodyProps) {
    return (
        <div className="flex flex-col items-center justify-center">
            <img
                className="rounded-full mb-10" 
                src={display.image} alt="" />
           <p className="text-white mx-10">{display.text}</p>
        </div>
    )
}

export

default Body

components/HeaderItem.tsx

type HeaderProps = {
    title: string,
    Icon: any,
    handleClick?: any,
}

function HeaderItem({title, Icon, handleClick}: HeaderProps ) {
 
    return (
        <button
            onClick={handleClick} 
            className="flex flex-col items-center cursor-pointer group w-12 sm:w-20 hover:text-white">
            <Icon className='h-8 mb-1 group-hover:animate-bounce '/>
            <h1 className='opacity-0 group-hover:opacity-100 tracking-widest'>{title}</h1>
        </button>
    )
}

export default HeaderItem

The end goal is for the image and text of the <Body > component to be updated to the new values when the appropriate button is clicked, i. e. when the Skills button is clicked, I would like the state to be updated from the Skills variable and display the associated text and image in the Body component. Thanks in advance


Solution 1:

The issue lay in the way I was passing props between from the state object into the Body component, and was exposed by naming things more idomatically, particularly renaming handleClick into onClick and passing it into HeaderItem as <button onClick={onClick}.... and in index.tsx, passing it like so

<HeaderItem onClick={() =>onClick(Intro)}...

<HeaderItem onClick={() => onClick(Skills)}... 

This allowed me to invoke the function correctly on click which updated my state object and passes the display down to the child Body component, where it is destructed into an image and text. Thank you for the help everyone, for both resolving the issue I had and teaching me along the way