admin管理员组

文章数量:1332345

Hi I am playing around with ReactJS, and found this awesome Modal Component to open Videoes in a Modal, but when I put the Modal inside a loop with multiple links and open the modal, it open like 5 times if I have 5 links. What do I do wrong?

Modal Component:

import React from 'react'
import ReactDOM from 'react-dom'enter code here
import ModalVideo from 'react-modal-video'

class App extends React.Component {
 constructor () {
    super()
    this.state = {
      isOpen: false
    }
    this.openModal = this.openModal.bind(this)
  }

  openModal () {
    this.setState({isOpen: true})
  }

      render () {
        return (
          <div>
            <ModalVideo channel='youtube' isOpen={this.state.isOpen} videoId='L61p2uyiMSo' />
            <button onClick={this.openModal}>Open</button>
          </div>
        )
      }
    }

    ReactDOM.render(
      <App />,
        document.getElementById('root')
    )

My Loop with the Modal Component Inside:

render(){
    return(
            <div>
                {(this.props.frag.all == null) ? null :
                  this.props.frag.all.map((frags, i) => {
                  return (
                  <li key={frags.id} className="group" id="" style={{width: 'calc(13% - 30px)'}}>
                    <ModalVideo channel='youtube' isOpen={this.state.isOpen} videoId='{frags.url}' />
                      <button onClick= {this.openModal.bind(this)}>Open</button>
                  </li>
                )})
              }
          </div>

Hi I am playing around with ReactJS, and found this awesome Modal Component to open Videoes in a Modal, but when I put the Modal inside a loop with multiple links and open the modal, it open like 5 times if I have 5 links. What do I do wrong?

Modal Component: https://github./appleple/react-modal-video

import React from 'react'
import ReactDOM from 'react-dom'enter code here
import ModalVideo from 'react-modal-video'

class App extends React.Component {
 constructor () {
    super()
    this.state = {
      isOpen: false
    }
    this.openModal = this.openModal.bind(this)
  }

  openModal () {
    this.setState({isOpen: true})
  }

      render () {
        return (
          <div>
            <ModalVideo channel='youtube' isOpen={this.state.isOpen} videoId='L61p2uyiMSo' />
            <button onClick={this.openModal}>Open</button>
          </div>
        )
      }
    }

    ReactDOM.render(
      <App />,
        document.getElementById('root')
    )

My Loop with the Modal Component Inside:

render(){
    return(
            <div>
                {(this.props.frag.all == null) ? null :
                  this.props.frag.all.map((frags, i) => {
                  return (
                  <li key={frags.id} className="group" id="" style={{width: 'calc(13% - 30px)'}}>
                    <ModalVideo channel='youtube' isOpen={this.state.isOpen} videoId='{frags.url}' />
                      <button onClick= {this.openModal.bind(this)}>Open</button>
                  </li>
                )})
              }
          </div>
Share Improve this question asked Feb 12, 2017 at 12:12 DbTheChainDbTheChain 2352 gold badges4 silver badges13 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

The problem is that each ModalComponent uses the same state property isOpen so when you click on any link it sets this property and each ModalComponent bees open. You should use unique property for each modal (you can use poperty which you already uses as key).

<li key={frags.id} className="group" id="" style={{width: 'calc(13% - 30px)'}}>
    <ModalVideo channel='youtube' isOpen={this.state.isOpen[frags.id]} videoId='{frags.url}' />
    <button onClick= {this.openModal.bind(this, frags.id)}>Open</button>
 </li>

And your method:

 openModal (id) {
    this.setState({
       isOpen: {
          [id]: true
       }
    });
 }

Reason is, you are using single state variable to maintain open/close status of modal, it will work properly for one, but in case of multiple modals, you have to use multiple state values to maintain the statuses, Use this:

Define isOpen as an array in state:

this.state= {
    isOpen=[],
}

Use this method to change the status of any particular modal:

openModal(index){
    let isOpen = this.state.isOpen.slice();
    isOpen[index] = true;
    this.setState({isOpen});
}

Bind the index of each modal in onClick method:

render(){
    return(
        <div>
            {(this.props.frag.all == null) ? null :
              this.props.frag.all.map((frags, i) => {
              return (
              <li key={frags.id} className="group" id="" style={{width: 'calc(13% - 30px)'}}>
                <ModalVideo channel='youtube' isOpen={this.state.isOpen[i] || false} videoId='{frags.url}' />
                  <button onClick= {this.openModal.bind(this,i)}>Open</button>
              </li>
            )})
          }
      </div>
    )
}

Modals in a loop are a bit plicated because they need a unique key for each row. Making the modal work without duplicating it is another challenge. The first mistake many of us make is including the modal within the loop. To prevent the duplication of the modal we need to make it fully dynamically. I have included a full example without having to duplicate the modal inside of the loop. I hope that helps

here is a full example

import React, { Component } from 'react';
import { Button, Alert, Input, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';

class History extends Component
{
    constructor(props)
    {
        super(props);
        this.state = {
        userHistory: [{'id': 1, 'test': 'this is a test'}, {'id': 2, 'test': 'this is a test2'}, {'id': 3, 'test': 'this is a test3'}],
            showLog: false,
            logID: null
        }
    }

    render() 
    {
        const history = this.state.userHistory.map( (ticket, key) =>
        {
            return (
                <tr key={key}>
                    <td>{ticket.test}</td>
                    <td>{ticket.id ? <Button  color="info" onClick={() => this.setState({logID:                          ticket.id, showLog: true})}>View</Button> : ''}</td>
                </tr>
            ) 
        });

        return (
            <div className="card-body">
                <table class="table table-striped">
                    <thead>
                        <tr> 
                            <th>test</th>
                            <th>modal</th>
                        </tr>
                    </thead>
                    <tbody>
                        {history}
                    </tbody>
                </table>
                    
                <Modal id={this.state.logID} isOpen={this.state.showLog} fade="false"  toggle={() => this.setState({showLog: false})}>
                    <ModalHeader toggle={() => this.setState({showLog: false})}>@jerryurenaa is awesome :D</ModalHeader>
                    <ModalBody>   
                        <p>Modal Number: {this.state.logID}</p>                     
                    </ModalBody>
                    <ModalFooter>
                        <Button onClick={() => this.setState({showLog: false})}>Cancel</Button>
                    </ModalFooter>
                </Modal>
            </div>
        );
    }
}


export default History;

本文标签: javascriptReactJS Modal opening multiple times when in a LoopStack Overflow