Using React state variable to change carousel slide

Hello,

I have a portfolio website I am working on here: Personal Portfolio.

In the about me section, there are embedded tabs to show information about different hobbies. Next to it, there is an image carousel. I’d like the images to change when the user selects different hobby tabs.

The active tab (in HobbyTabs.js) is stored in a state variable and passed up to the parent (about-me.js) and down to the sibling (ImageCarousel.js). The variable changes as expected in a heading above the component. Yet, that component does not register a change in that state correctly when used in the ‘activeIndex=’ property.

Any suggestions as to why this issue is occurring, how to fix it, or a better way to achieve the same thing are welcomed!

Here are the three blocks of code referenced.

about-me.js
import { Row, Col, Image, Container} from "react-bootstrap";
import { ImageCarousel } from "../components/ImageCarousel"
import { HobbyTabs } from "../components/HobbyTabs"
import { useState, useEffect, createContext } from "react";

export const Context = createContext()
export default function AboutMe() {
    const [key, setKey] = useState(0)

    useEffect(() => console.log(key))

    return (
        <main style={{ padding: "1rem 0"}} >
           <Container>
                <Row>
                    <Col className="text-center">
                        <h2>Who is Elliot Erickson, really?</h2>
                    </Col>
                </Row>
                <Row className="align-items-center">
                    <Col md={4}>
                        <p className="lead font-weight-bold">
                        Mūsa, mihī causās memorā, quō nūmine laesō
                        </p>
                        <p className="lead font-weight-bold">Quidve dolēns, rēgīna deum tot volvere cāsūs  īnsīgnem pietāte virum, tot adīre labōrēs impulerit.</p>
                        <p className="lead font-weight-bold">Tantaene animīs caelestibus īrae?  Urbs antīqua fuit, Tyriī tenuēre colōnī. </p>  
                    </Col>
                    <Col md={8}>
                        <Image src={require("../images/about-me-profile.PNG")} className="img-fluid d-none d-sm-block" alt="Portfolio Preview" />
                    </Col>
                </Row>
                <Row>
                    <Context.Provider value={{key, updateKey: key => setKey(key)}}>
                        <HobbyTabs />
                        <ImageCarousel />
                    </Context.Provider>
                </Row>
           </Container>
        </main>
    );
}
HobbyTabs.js

import { Col, Tabs, Tab } from "react-bootstrap";
import { useContext } from "react";
import { Context } from "../routes/about-me"

export const HobbyTabs = () => {
    const {key, updateKey } = useContext(Context)

    return (
        
        <Col className="mt-5" md={6}>
       
            <h2 className="text-center">Hobbies and Interests</h2>
            <Tabs
                activeKey={key}
                transition={false}
                onSelect={(k) => 
                    updateKey(k)
                }
                id="hobby-tabs-no-animation"
                className="mb-3"
            >
                <Tab 
                    eventKey={0} 
                    title="Hobby One"
                    >
                    <p className="lead">
                    Hīs accēnsa super iactātōs aequore tōtō Trōas, rēliquiās Danaum atque immītis Achillī, arcēbat longē Latiō, multōsque per annōs errābant, āctī Fātīs, maria omnia circum.Tantae mōlis erat Rōmānam condere gentem!
                    </p>
                </Tab>
                <Tab 
                    eventKey={1}
                    title="Hobby Two"
                    >
                    <p className="lead">
                    Aeolus haec contra: 'Tuus, O regina, quid optes explorare labor; mihi iussa capessere fas est. Tu mihi, quodcumque hoc regni, tu sceptra Iovemque concilias, tu das epulis accumbere divom, nimborumque facis tempestatumque potentem.'
                    </p>
                </Tab>
                <Tab 
                    eventKey={2}
                    title="Hobby Three"
                    >
                    <p className="lead">
                    Haec ubi dicta, cavum conversa cuspide montem impulit in latus: ac venti, velut agmine facto, qua data porta, ruunt et terras turbine perflant. Incubuere mari, totumque a sedibus imisna Eurusque Notusque ruunt creberque procellis Africus, et vastos volvunt ad litora fluctus.
                    </p>
                </Tab>
            </Tabs>  
        </Col>
    );
  };
ImageCarousel.js

import { Carousel, Col } from 'react-bootstrap';
import { Context } from "../routes/about-me"
import {  useContext, useState} from "react";


export const ImageCarousel = () => {

    const { key } = useContext(Context);

    return (
        <Col>
        <h2>the key is {key}</h2>
 
        <Carousel 
            
            variant="dark" 
            interval={null} 
            controls={false} 
            indicators={false} 
            activeIndex={key}
            >
    
            <Carousel.Item >
                <img
                className="d-block w-100"
                src={require("../images/hobby-image.PNG")}
                alt="First slide"
                />
                <Carousel.Caption>
                <h3 className="text-success">First slide label</h3>
                </Carousel.Caption>
            </Carousel.Item>
            <Carousel.Item >
                <img
                className="d-block w-100"
                src={require("../images/hobby-image.PNG")}
                alt="Second slide"
                />
                <Carousel.Caption>
                <h3 className="text-success">Second slide label</h3>
                </Carousel.Caption>
            </Carousel.Item>
            <Carousel.Item >
                <img
                className="d-block w-100"
                src={require("../images/hobby-image.PNG")}
                alt="Third slide"
                />
                <Carousel.Caption>
                <h3 className="text-success">Third slide label</h3>
                </Carousel.Caption>
            </Carousel.Item>
        </Carousel>
        </Col>
    )
}

Thank you!!

Drop it in a codepen or similar and people will have an easier time debugging it.

You’re using the same image file for all three images right now. You should be able to render different images based on the value of key. Unless you really want a carousel, you could just render the image with that component. If you really want a carousel, then the hobby tabs and the carousel controls should both update each other (IMHO).

The first thing I would do is drop a console.log(k) in the tabs onselect() function to see what is happening there. onSelect() is an event handler and expects an event as it’s argument and my guess is (without running the code) is that k is an event and not your index (hopefully the index is in the event object somewhere…).

Hey @jeremy.a.gray

Thanks for the thoughts! I really appreciate the console.log tips as I have trouble deciding where they should go.

Which component do you mean by “render the image with that component”? The Tabs? I used a carousel just out of curiosity if it would work, so I’m not married to it.

I think I understand the distinction between the “key” as an event and not the actual tab index. I hadn’t thought of that either.

Lastly, as for codepen, I see how that is way better to help debug this. BUT I have no idea how to drop this code into codepen and get it to work. Not sure if it is using react-router (which also causes issues in GitHub pages), or If I am not copy-pasting things correctly, or not loading the right dependencies…

Let me work on what you’ve said here, if I still can’t get it, I’ll work on putting the code in codepen.

Thanks again!

It seems to work if I convert the key to a number inside the HobbyTabs component in the onSelect callback.

onSelect={(k) => updateKey(Number(k))}

I did also update react-bootstrap to 2.4.0 as there may have been a fix for the Carousel component.

https://github.com/react-bootstrap/react-bootstrap/pull/6265


You can use CodeSandbox or StackBlitz. Or just post the GitHub repo.

https://github.com/MoxElliot/personal-portfolio


Example (I had to remove the basename="/personal-portfolio" on BrowserRouter)

1 Like

Dear god thank you! Spent all day messing around with it, really appreciate the help!!