Reactjs组件模态onclick div

时间:2018-03-26 10:09:55

标签: reactjs modal-dialog components

我正在尝试创建一个我可以重用的模态组件,但是我不知道我在这里做错了什么。莫代尔没有出现。任何人都可以帮助我吗?

关于我的应用的一点解释。 这个应用程序正在加载一个JSON URL并显示一个产品列表,可以标记为已完成。如果你单击div plaatjediv,你应该得到一个弹出窗口(模态),其中包含所点击产品的详细信息。

编辑:按照此处的建议编辑代码。如果单击div,我可以看到状态更改为true和false,但Modal仍然没有出现。

我的代码

App.js

import React from 'react';
import ProductModal from './ProductModal.js';


 class App extends React.Component {

    constructor(props) {
        super(props);
        this.toggleModal = this.toggleModal.bind(this);
        this.state = {
            isLoading: true,
            orders: [],
            dealtOrders: [],
            open: false
        }
    }

    toggleModal() {
        this.setState({
            open: !this.state.open
        });
    }

    componentWillMount() {
        localStorage.getItem('orders') && this.setState({
            orders: JSON.parse(localStorage.getItem('orders')),
            isLoading: false
        })
    }

    componentDidMount() {
        if (!localStorage.getItem('orders')){
            this.fetchData();
        } else {
            console.log('Using  data from localstorage');
        }
    }

    fetchData() {
        fetch('http://localhost:54408/api/orders/all/26-03-2018')
            .then(response => response.json())
            .then(parsedJSON => parsedJSON.map(product => (
                {
                    productname: `${product.ProductName}`,
                    image: `${product.Image}`,
                    quantity: `${product.Quantity}`,
                    isconfirmed: `${product.IsConfirmed}`,
                    orderid: `${product.OrderId}`
                }
            )))
            .then(orders => this.setState({
                orders,
                isLoading: false
            }))
            .catch(error => console.log('parsing failed', error))
    }

    render() {
        this.handleDoneAction = event =>
        {
            let itemIndex = event.target.getAttribute("data-itemIndex");
            let prevOrders = [...this.state.orders];
            let dealtOrders = [...this.state.dealtOrders];
            const itemToMoveAtLast = prevOrders.splice(itemIndex, 1);
            const addToDealtOrders = dealtOrders.concat(itemToMoveAtLast);
            this.setState({dealtOrders: addToDealtOrders});
            this.setState({orders: prevOrders});
        };

        this.handleUndoAction = event =>
        {
            let itemIndex = event.target.getAttribute("data-itemIndex");
            let orders = [...this.state.orders];
            let dealtOrders = [...this.state.dealtOrders];
            const undoDealtOrder = dealtOrders.splice(itemIndex, 1);
            const addToOrders = orders.concat(undoDealtOrder);
            this.setState({orders: addToOrders});
            this.setState({dealtOrders: dealtOrders});
        };

        const {isLoading, orders, dealtOrders,open} = this.state;
    return (
        <div>
            <header>
                <img src="/images/header.jpg"/>
                <h1>Boodschappenlijstje <button className="btn btn-sm btn-danger">Reload</button></h1>
            </header>
            <ProductModal open={open} />

                <div className={`content ${isLoading ? 'is-loading' : ''}`}>
                    <div className="panel">
                        {
                            !isLoading && orders.length > 0 ? orders.map((order, index) => {
                            const {productname, image, quantity, orderid} = order;
                            return<div className="product" key={orderid}>
                                <div className="plaatjediv" onClick={this.toggleModal}>
                                    <img className="img-responsive" src={image} />
                                </div>
                                <div className="productInfo">
                                    <p>{productname}</p>
                                    <p>Aantal: {quantity}</p>
                                </div>
                                <div className="bdone">
                                    <button className="btn btn-lg btn-default btndone" data-itemIndex={index} onClick={this.handleDoneAction}>Done</button>
                                </div>
                            </div>
                        }) : null
                        }
                    </div>
                    <h2>Mandje</h2>
                    <div className="panel">
                        {
                            !isLoading && dealtOrders.length > 0 ? dealtOrders.map((dorder, index) => {
                                const {productname, image, quantity, orderid} = dorder;
                                return<div className="productDone" key={index}>
                                    <div className="plaatjediv">
                                        <img className="img-responsive" src={image} />
                                    </div>
                                    <div className="productInfo">
                                        <p>{productname}</p>
                                        <p>Aantal: {quantity}</p>
                                    </div>
                                    <div className="bdone">
                                        <button className="btn btn-lg btn-default btndone" data-itemIndex={index} onClick={this.handleUndoAction}>Undo</button>
                                    </div>
                                </div>
                            }) : null
                        }
                    </div>
                    <div className="loader">
                        <div className="icon"></div>
                    </div>
                </div>
            </div>
        );
    }
} export default App;

ProductModal.js

  import React from 'react';

 class ProductModal extends React.Component {
constructor() {
    super();
}

render() {
    const open = this.props.open;
    return (
        <div className={'modal fade'+(open ? '' : 'hide')} tabindex="-1" role="dialog">
            <div className="modal-dialog">
                <div className="modal-content">
                    <div className="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                        <h4 className="modal-title">test</h4>
                    </div>
                    <div className="modal-body">
                        test
                    </div>
                    <div className="modal-footer">
                        <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
                        <button type="button" className="btn btn-primary">Save changes</button>
                    </div>
                </div>
            </div>
        </div>
    )
}
 }

 export default ProductModal;

3 个答案:

答案 0 :(得分:2)

我无法看到模拟应该在哪里呈现。你必须将它添加到你的&#34; App&#34;的渲染功能中。类。像这样:

render() {
  ...
  return(
    <ProductModal open={true} />
    ...
  ):
}

并且,在您的toggleModal函数中,执行以下操作:

this.setState({ open: !this.state.open});

希望这可以解决问题。

答案 1 :(得分:1)

我不确定你的问题是什么问题,但我猜你的模特还没开?

设置状态时,需要将其设置为this.state.open

的反面

你可以这样做:

toggleModal() {
    this.setState({
        open: !this.state.open
    });
}

答案 2 :(得分:1)

问题是你没有将<ProductModal />作为<App />中的一个组件除了设置你的开放状态,一旦显示,它将(或应该)永远不会隐藏,因为你不会能够使用您的按钮再次切换它,并且您的<ProductModal />内也没有任何键绑定。

我建议你将<ProductModal />中的事件监听器绑定到

  1. 检查是否按下ESC键
  2. 绑定取消/关闭按钮(除标题x按钮外)。
  3. 如果单击对话框外的任何位置,请忽略该模式。
  4. 您还需要将处理程序从<App />传递到<ProductModal />以通知模式已关闭。

    在你的App.js

    handleClose() {
        this.setState({
            open: false
        });
    }
    
    render() {
        return (
            ...
            <ProductModal open={this.state.open} handleClose={this.handleClose.bind(this)} />
        )
    }
    

    然后在您的ProductModal.js

    handleClose() {
        this.props.handleClose();
    }
    

    使用我的沙箱观察以下内容: https://stackblitz.com/edit/react-98m4cr

    您已经看到我已经实施了handleClose事件来控制状态回到父级。另外,您可能希望添加上面提到的侦听器,最后全部触发handleClose;只需记住在ProductModal.js componentWillUnmount中取消绑定它们。