【问题标题】:Reactjs component modal onclick divReactjs 组件模态 onclick div
【发布时间】:2018-03-26 10:09:55
【问题描述】:

我正在尝试制作一个可以重用的模态组件,但我不明白我在这里做错了什么。模态没有出现。谁能帮帮我?

关于我的应用的一点解释。 这个应用程序正在加载一个 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;

【问题讨论】:

  • this.state.modal => 你的状态没有模态。在进行切换时,最好这样做:this.setState(prevState =&gt;({open:!prevState.modal})),根据之前的模态值进行切换。当您在状态中定义“模态”时。
  • 您遇到了什么具体问题

标签: reactjs modal-dialog components


【解决方案1】:

我看不到模态框应该在哪里呈现。您必须将其添加到“App”类的渲染功能中。像这样:

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

另外,在您的 toggleModal 函数中,执行以下操作:

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

希望这能解决问题。

【讨论】:

  • 谢谢你的作品!如果我单击 div,我可以看到状态发生了变化,但 Modal 没有出现。知道为什么吗?另外,open={true} 在哪里?
  • open={true} 更改为 open={this.state.open} 效果更好:)。但是模态仍然没有出现。
  • 这可能是因为您的className={'modal fade'+(open ? '' : 'hide')} 以及您如何设置它。但我看到你已经解决了这个问题。祝你好运(y)
【解决方案2】:

问题是您的&lt;App /&gt; 中没有您的&lt;ProductModal /&gt; 作为组件除了设置您的打开状态,一旦显示,它将(或应该)永远不会隐藏,因为您将无法切换它再次使用您的按钮,并且您的 &lt;ProductModal /&gt; 本身也没有任何键绑定。

我建议你将&lt;ProductModal /&gt; 中的事件监听器绑定到

  1. 检查是否按下了 ESC 键
  2. 绑定一个取消/关闭按钮(除了标题 x 按钮)。
  3. 监听是否点击了对话框之外的任何地方,关闭模式。

您还需要将处理程序从 &lt;App /&gt; 向下传递到 &lt;ProductModal /&gt; 以通知模式何时关闭。

在您的 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 中解绑它们。

【讨论】:

  • 感谢您的建议。正如 Amir 所提到的,我在我的 app.js 中添加了&lt;ProductModal open={this.state.open} /&gt; 当我单击 div 时,会看到状态发生变化以及我的 ProductModal 中的类,但它没有出现。你知道为什么吗?
  • @valheru 我没有,你能更新你的代码以便我们看到吗?我们只看到你的import 的组件,但它不存在于你的render()
  • 我也认为你想要的是modal in vs modal。我认为您不需要hide,这可能会使事情复杂化。给我几分钟,我给你看。
  • @valheru 刚刚添加了一个快速沙箱,其中包含您的组件,说明了一个工作示例
  • 是的!这就像一个魅力,非常感谢你:)
【解决方案3】:

我不确定你的问题是什么,但我猜你的模型没有打开?

设置状态时,需要设置为this.state.open的反面

你可以这样做:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    相关资源
    最近更新 更多