简体   繁体   中英

Change State of an image based on index of array - React.js

I have an array of cards with some svg that needs to change sate individually (up and down) based on click. the modal is handled by bootstrap. so,I am trying to change the state of a svg (hard coded) based on the index of an array. However, even if I get the id (that is dynamic), everytimes I click on the svg arrow, all the svg are changing states.

I think the state should not be changed in the for loop and I wonder if the issue could be from {this.state.arrowShown && }. Therefore, how can I only change the svg state of the card that is clicked without changing the state of others?

import Container from 'react-bootstrap/Container'
import Card from 'react-bootstrap/Card'
import Row from 'react-bootstrap/Row'
import Col from 'react-bootstrap/Col'
import { withTranslation } from 'react-i18next';
import Accordion from 'react-bootstrap/Accordion'
import Button from 'react-bootstrap/Button'

class ProjectCard extends React.Component {

    constructor() {
        super();
        this.state = {
            arrowShown: true,
            arrowHidden: false,
        }
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick(event, index) {
        const id = event.currentTarget.id;
        const projectArr = this.props.projects;
        console.log("this.props.porjects", this.props.projects)
        for (var i = 0; i < projectArr.length; i++) {
            console.log("projectArr[i].idP1", projectArr[i].idP2)
            if (projectArr[i].idP2 === id) {
                console.log("same same")
                this.setState({
                    arrowShown: !this.state.arrowShown,
                    arrowHidden: !this.state.arrowHidden
                })
                // newState[projectArr[i].idP2.arrowShown] = projectArr[i].idP2 === projectArr[i].idP2
            }
        }
        //     // this.setState(newState)
        // }
    }
    render() {
        const { t } = this.props;
        // arrowHidden = {}
        return (
            <React.Fragment>
                <Container fluid className=" pb-5" id="Projects">
                    <Row className="d-flex justify-content-center py-5" xs={1} md={1} lg={3}>
                        {this.props.projects.map((project, index) => (
                            <Col className="d-flex justify-content-center px-5 py-5" key= 
                               {project.keyP}>
                                <Card className="bg-warning" border="light" >
                                    <Card.Img variant="top" src={project.srcP} 
                                    className="overlay" />
                                    <Card.Body className="bg-light">
                                        <Card.Title className="text-warning" > 
                                        t(project.titleP)}</Card.Title>
                                        <Card.Text>
                                            {t(project.descriptionP)}
                                        </Card.Text>
                                        <Accordion>

                                            <Accordion.Toggle as={Button} variant="link" 
                                               eventKey="0" className="p-0" id={project.idP1}  >
                                                <Card.Title className="text-warning" >
                                                    Features

                                                 {this.state.arrowShown
                                                        <svg id={project.idP2} onClick={(event) => { this.handleClick(event, index) }} width="1em" height="1em" viewBox="0 0 16 16" className=" down bi bi-chevron-double-down" fill="currentColor" xmlns="http://www.w3.org/2000/svg" >
                                                            <path fillRule="evenodd" d="M1.646 6.646a.5.5 0 0 1 .708 0L8 12.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z" />
                                                            <path fillRule="evenodd" d="M1.646 2.646a.5.5 0 0 1 .708 0L8 8.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z" />
                                                        </svg>

                                                    }
                                                    {this.state.arrowHidden &&


                                                        <svg id={project.idP3} onClick={(event) => { this.handleClick(event, index) }} width="1em" height="1em" viewBox="0 0 16 16" className=" up bi bi-chevron-double-up" fill="currentColor" xmlns="http://www.w3.org/2000/svg"  >
                                                            <path fillRule="evenodd" d="M7.646 2.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 3.707 2.354 9.354a.5.5 0 1 1-.708-.708l6-6z" />
                                                            <path fillRule="evenodd" d="M7.646 6.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 7.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z" />
                                                        </svg>
                                                    }
                                                </Card.Title>
                                            </Accordion.Toggle> ```

ps: it is my first question so every feedback is welcome! Thank you for your support.

[enter image description here][1]


  [1]: https://i.stack.imgur.com/0YD01.png

you are changing the state for each image here


this.setState({
        arrowShown: !this.state.arrowShown,
        arrowHidden: !this.state.arrowHidden
    })

and showing each image with the same state value. thats why all of the images are flipped any time you flip for one.

What you can do is maintain a state something like this


       this.state = {  
           [index1] : { arrowShown : true , arrowHidden :false }  ,
           [index2] : { arrowShown : true , arrowHidden :false }  ,
       //and so on
       }

then whenever based on the index of the clicked image you only update the state for that particular index like this...


       this.setState({[indexOfTheClickedImage ] : { 
                arrowShown: !this.state.[indexOfTheClickedImage].arrowShown ,
                arrowHidden: !this.state.[indexOfTheClickedImage].arrowHidden
       }}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM