简体   繁体   English

当我通过列表映射时,React-bootstrap 模态组件打开/关闭所有模态

[英]React-bootstrap Modal component opens/closes all modals when I map through a list

New to programming so I'm sorry if I'm not wording this correctly.编程新手,所以如果我的措辞不正确,我很抱歉。 I'm using a .map to render and list every single item on an array.我正在使用 .map 来呈现和列出数组中的每个项目。 For each item, I want the modal to open/close only the specific modal corresponding to each item in the array.对于每个项目,我希望模态仅打开/关闭与数组中每个项目对应的特定模态。 However, when I click on the button to open the modal, every single one opens and closes.但是,当我单击按钮打开模态时,每一个都会打开和关闭。 I believe this is because the modals are all set to an on/off button together.我相信这是因为模态都一起设置为开/关按钮。 How can I set it it (with the .map value.id or something) so that only the specific modal opens and closes?我如何设置它(使用 .map value.id 或其他东西)以便只有特定的模式打开和关闭?

class DrinkMenu extends Component {
    constructor(props, context) {
        super(props, context);
        this.state = {
            show: false
        };
        this.handleHide = this.handleHide.bind(this);
    }

    handleHide() {
        this.setState({ show: false });
    }

    async componentDidMount() {
        let res = await axios.get('/getAllDrinks')
        this.props.updateDrinkMenu(res.data)
    }

    async addToCart(drinkObj) {
        let res = await axios.post('/addToCart', drinkObj)
        console.log(`Added ${drinkObj.name} to order.`)
    }

    render() {
        let drinkList = this.props.drinkMenu.map((drink) => {
            return (
                <div key={drink.id}>
                    <h5>{drink.name}</h5>
                    <h6>${drink.price}</h6>

                    <span
                        onClick={() => this.setState({ show: true })}
                    >
                        <strong>More Info</strong>
                        <br />
                        <button onClick={() => this.addToCart(drink)}>Add to Order</button>

                    </span>

                    <Modal
                        show={this.state.show}
                        onHide={this.handleHide}
                        container={this}
                        aria-labelledby="contained-modal-title"
                    >
                        <Modal.Header closeButton>
                            <Modal.Title id="contained-modal-title">
                                {drink.name}
                            </Modal.Title>
                        </Modal.Header>
                        <Modal.Body>
                            <p>{drink.sub_category} | ABV {drink.abv}% | {drink.origin}</p>
                            <Col xs={6} md={4}>
                                <Image className="drink-logo" src={drink.logo} thumbnail />
                            </Col>
                            <p className="drink-description"><strong>Description</strong><br />{drink.description}</p>
                            <p href={drink.website}>Website</p>
                        </Modal.Body>
                        <Modal.Footer>
                            <Button onClick={this.handleHide}>Close</Button>
                        </Modal.Footer>
                    </Modal>
                </div>
            )
        })

        return (
            <div>
                <h2>Drink Menu</h2>
                <div>
                    {drinkList}
                </div>
            </div>
        )
    }
}

From the code you have shared, I see that you are handling all the Model with the same state value, ie show .从您共享的代码中,我看到您正在处理具有相同状态值的所有Model ,即show This is causing all the state for all the Models to be true hence all of them as shown.这导致所有Models所有状态都为true因此如图所示。

To solve this, you can extract your whole component in a new React class which has just the functionality to show Modal as per the independent state.为了解决这个问题,您可以将整个组件提取到一个新的React类中,该类仅具有根据独立状态显示Modal的功能。 So your new React component will look something like this:所以你的新 React 组件看起来像这样:

class DrinkComponent extends React.Component {
    constructor(props) {
        super(props);
        this.handleHide = this.handleHide.bind(this);
        this.state = {
            show: false,
        }
    }
    handleHide() {
        this.setState({ show: false });
    }
    render() {
        const { drink } = this.props;
        return (<div key={drink.id}>
            <h5>{drink.name}</h5>
            <h6>${drink.price}</h6>
            <span
                onClick={() => this.setState({ show: true })}
            >
                <strong>More Info</strong>
                <br />
                <button onClick={() => this.props.addToCart(drink)}>Add to Order</button>
            </span>
            <Modal
                show={this.state.show}
                onHide={this.handleHide}
                container={this}
                aria-labelledby="contained-modal-title"
            >
                <Modal.Header closeButton>
                    <Modal.Title id="contained-modal-title">
                        {drink.name}
                    </Modal.Title>
                </Modal.Header>
                <Modal.Body>
                    <p>{drink.sub_category} | ABV {drink.abv}% | {drink.origin}</p>
                    <Col xs={6} md={4}>
                        <Image className="drink-logo" src={drink.logo} thumbnail />
                    </Col>
                    <p className="drink-description"><strong>Description</strong><br />{drink.description}</p>
                    <p href={drink.website}>Website</p>
                </Modal.Body>
                <Modal.Footer>
                    <Button onClick={this.handleHide}>Close</Button>
                </Modal.Footer>
            </Modal>
        </div>);
    }
}

In this case, each DrinkComponent will have its independent state of showing and hiding of the model.在这种情况下,每个DrinkComponent将有其独立的模型显示和隐藏状态。 Now we have to just modify your existing render function in DrinkMenu , to display DrinkComponent .现在我们只需修改DrinkMenu现有的render函数,以显示DrinkComponent So your render function will look something like this:所以你的render函数看起来像这样:

render() {
        let drinkList = this.props.drinkMenu.map((drink) => (<DrinkComponent drink={drink} addToCart={this.addToCart}/>));
        return (
            <div>
                <h2>Drink Menu</h2>
                <div>
                    {drinkList}
                </div>
            </div>
        )
    }

Also you can remove the show state from DrinkMenu as it wont be needed there.您也可以从DrinkMenu删除显示state ,因为那里不需要它。 Hope it helps.希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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