Модалы реакции отображаются сразу при нажатии кнопки

#javascript #reactjs #react-hooks

Вопрос:

Реагируй, новичок. Я видел предыдущие предложения SO, но они не помогают мне в той схеме, которой я следовал здесь. Пожалуйста, может ли кто-нибудь сказать мне, как я определяю, что нажатая кнопка запускает только соответствующий модал в этом коде? Я хотел бы получить некоторую помощь в работе над этим кодом, так как потребовалось некоторое время, чтобы собрать его воедино, и я понимаю кое-что из того, что здесь происходит. Опытные программисты увидят здесь мои детские шаги. Спасибо.

This is the returned json

 {
    "cakes": [
        {
            "id": 1,
            "text": "Fruit Sponge Layer Cake",
            "comment": "Real fruit - strawberries, Victoria Sponge and cream",
            "image": "./assets/fruitLayerSponge.jpg",
            "alt": "Fruit Sponge",
            "yum": 1,
            "name": "fruitSponge"
        },
        {
            "id": 2,
            "text": "Chocolate Muffin",
            "comment": "Chocolate mix, chocco chips and cream",
            "image": "./assets/chocoMuffinsWCream.jpg",
            "alt": "Chocco Muffin",
            "yum": 3,
            "name": "choccoMuffin"
        },
        {
            "id": 3,
            "text": "Strawberry Cheesecake",
            "comment": "Cheesecake with strawberry cream",
            "image": "./assets/strawberryCheesecake.jpg",
            "alt": "Cheesecake",
            "yum": 2,
            "name": "cheesecakeStrawberry"

        }
    ]
}
 

This is the React Component - AsyncAwaitLocalhost.jsx

 import React from 'react';
import "./App.css"
import { Modal, Button } from "react-bootstrap";

class AsyncAwaitLocalhost extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            jsonContent: [],
            greeting: "string",
            newGreeting: "Hello",
            isOpen: false
        };
    }


    async componentDidMount() {
        // GET request using fetch with async/await
        const response = await fetch('http://localhost:8080/cakes');
        const data = await response.json();
        this.setState({ jsonContent: data.cakes, greeting: this.state.greeting, newGreeting: this.state.newGreeting })

    }

    openModal = () => this.setState({ isOpen: true });

    closeModal = () => this.setState({ isOpen: false });

    render() {
        const { jsonContent } = this.state;
        const { greeting } = this.state;
        const { newGreeting } = this.state;
        this.state.greeting = "Hello greeting";
        this.state.newGreeting = "Hi new greeting";
        console.log("greeting: "   greeting);
        console.log("newGreeting: "   newGreeting);

        // the inline JSX render component definition
        const Cake = ({ name, id, text, image, comment, dbutton, dmodal }) => (
            <div>
                <img src={image} width="120px" alt={name}/>
                <div>
                    <p>{name}</p>
                    <p>{text}</p>
                    <p>{comment}</p>
                    <p>{id}</p>
                    <div>{dbutton}</div>
                    <p>amp;nbsp;</p>
                    <div id="dModal" className="dModalClosed">{dmodal}</div>
                    <p>amp;nbsp;</p>
                </div>
            </div>
        );

        return (

            <div className="card text-center m-3">
                <h5 className="card-header">See Cakes</h5>
                <div className="card-body">
                    <div>
                        {this.state.jsonContent.map((cake, index) => (
                            <Cake
                                name={`${cake.id} ${cake.name}`}
                                image={cake.image}
                                text={cake.text}
                                comment={cake.comment}
                                key={index}
                                dbutton={<Button onClick={this.openModal}>See more {cake.id}</Button>}
                                dmodal={
                                    <Modal id={cake.name} show={this.state.isOpen} onHide={this.closeModal}>
                                        <Modal.Header closeButton>
                                            <Modal.Title>{cake.text}</Modal.Title>
                                        </Modal.Header>
                                        <Modal.Body>name={`${cake.id} ${cake.name}`}
                                            image={cake.image}
                                            text={cake.text}
                                            comment={cake.comment}
                                        </Modal.Body>
                                        <Modal.Footer>
                                            <Button variant="secondary" onClick={this.closeModal}>
                                                Close
                                            </Button>
                                        </Modal.Footer>
                                    </Modal>
                                }
                            />
                        ))}
                        <div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

export { AsyncAwaitLocalhost };
 

Комментарии:

1. В настоящее время вы используете одно и то же isOpen состояние для всех модалов. Вам нужно будет отслеживать состояние «открыто» для каждого отдельного модала.

Ответ №1:

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

 this.state = {
  isOpen: null
};
...
onClick={this.openModal(index)}
...
openModal = (index) => () => this.setState({ isOpen: index });
closeModal = () => this.setState({ isOpen: null });
...
show={this.state.isOpen === index}
 

Комментарии:

1. Спасибо @Viet. Реализация вашего решения заняла минуту или две, и проблема была решена немедленно.

Ответ №2:

Обе эти линии меняются isOpen в зависимости от вашего состояния AsyncAwaitLocalhost .

 openModal = () => this.setState({ isOpen: true });

closeModal = () => this.setState({ isOpen: false });
 

Все ваши модалы настроены на отображение, когда this.state.isOpen это верно:

 <Modal id={cake.name} show={this.state.isOpen} onHide={this.closeModal}>
 

Таким образом, всякий раз , когда вы устанавливаете this.state.isOpen значение true на своем AsyncAwaitLocalhost , как это происходит всякий раз, когда вы звоните openModal() , будут отображаться все модалы.

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