簡體   English   中英

如何選擇 React 中的所有復選框?

[英]How to select all checkboxes in React?

我有這個模塊:

import React, { Component } from 'react'
import EmailListItem from './EmailListItem'
import { createContainer } from 'meteor/react-meteor-data'
import { Emails } from '../../../../../imports/collections/emails/Emails'

class EmailList extends Component {
  constructor (props) {
    super(props)
    this.state = {
      selectedEmails: new Set(),
      checked: false
    }
  }

  handleSelectedEmails (selectedEmail, checked) {
    let selectedEmails = this.state.selectedEmails
    if (checked) {
      selectedEmails.add(selectedEmail)
    } else {
      selectedEmails.delete(selectedEmail)
    }
    this.setState({selectedEmails})
    console.log('selectedEmails', this.state.selectedEmails)
  }
  removeSelected () {
    const selectedEmails = Array.from(this.state.selectedEmails)
    Meteor.call('emails.remove', selectedEmails, (err, result) => {
      if (err) console.log(err)
      if (result) console.log(result)
    })
  }
  checkedClick () {
    this.setState({checked: !this.state.checked})
    console.log('chcekedClick')
  }
  renderList () {
    console.log(this.props)
    return this.props.emails.map(email => {
      console.log(email)
      const { name, opr, ctr, _id } = email
      const createdAt = email.createdAt.toDateString()
      const link = `/dashboard/emailpreview/${_id}`
      return (
        <EmailListItem
          selecetedAllEmails={this.state.checked}
          handleSelectedEmails={this.handleSelectedEmails.bind(this)}
          name={name}
          createdAt={createdAt}
          opr={opr}
          ctr={ctr}
          link={link}
          key={email._id}
          id={email._id} />
        )
    })
  }
  render () {
    // TODO: make checks with state
    return (
      <div className="email_list">
        <table>
          <thead>
            <tr>
              <td><input onChange={this.checkedClick.bind(this)} type="checkbox" checked={this.state.checked} /></td>
              <td>Title<button onClick={this.removeSelected.bind(this)} className="btn btn-danger">Remove</button></td>
              <td>Dates</td>
              <td>Open Rates</td>
              <td>CTA</td>
            </tr>
          </thead>
          <tbody>
            {this.renderList()}
          </tbody>
        </table>

      </div>
  )
  }
}

export default createContainer(() => {
  Meteor.subscribe('emails')
  return { emails: Emails.find({}).fetch() }
}, EmailList)

它呈現這個模塊

import React, { Component } from 'react'
import { Link } from 'react-router'

class EmailListItem extends Component {
  constructor (props) {
    super(props)
    this.state = {
      checked: false
    }
  }

  checkedClick () {
    this.setState({checked: !this.state.checked})
    console.log('chcekedClick')
  }

  componentDidUpdate () {
    console.log('componentDidUpdate')
    const { myCheckbox } = this.refs
    console.log('myCheckbox', myCheckbox)
    console.log('myCheckbox.name', myCheckbox.name)
    console.log('myCheckbox.checked', myCheckbox.checked)
    if (this.props.selecetedAllEmails) {
      console.log('componentDidUpdate IF')
      this.checkedClick()
      this.props.handleSelectedEmails(myCheckbox.name, myCheckbox.checked)
    }
  }
  render () {
    console.log('_id', this.props.id)
    return (
      <tr>
        <td><input ref="myCheckbox"
          onChange={(event) => {
            this.checkedClick()
            this.props.handleSelectedEmails(event.target.name, event.target.checked)
          }}
          checked={this.state.checked}
          type="checkbox" name={this.props.id} /></td>
        <td><Link to={this.props.link}>{this.props.name}</Link></td>
        <td>{this.props.createdAt}</td>
        <td>Open Rates</td>
        <td>CTA</td>
      </tr>
    )
  }
}

export default EmailListItem

如您所見,對於每個電子郵件項目,我都有一個復選框。 我可以選擇幾個復選框,然后單擊該刪除按鈕,該按鈕將調用刪除我選擇的項目。 現在在頂部我有一個復選框,它應該選擇所有復選框。 我對此的解決方案是存儲選中的全局復選框並將其作為道具傳遞給所有項目。 然后在項目中我對 componentDidUpdate 執行檢查,如果全局復選框被選中,那么我也會檢查該項目。 但這會導致無限循環。 這里最好的解決方案是什么?

雖然一些答案提供了選擇所有復選框的特定功能,但我還需要一些通用功能,例如取消選擇所有,選擇所有然后取消選擇一些,手動選擇所有選擇所有復選框時也選中等等......所以我寫了所有並將其作為答案發布在這里。 感謝所有回復的人。 此代碼基於 Mayank Shuklas 答案。 請注意,它可能仍然不完美,因為我還沒有對其進行適當的測試,而且肯定需要進行一些重構。

import React, { Component } from 'react'
import EmailListItem from './EmailListItem'
import { createContainer } from 'meteor/react-meteor-data'
import { Emails } from '../../../../../imports/collections/emails/Emails'

class EmailList extends Component {
  constructor (props) {
    super(props)
    this.state = {
      selectedEmails: new Set(),
      checked: false
    }
  }

  handleSelectedEmails (allSelected, individualSelected, selectedEmail, checked) {
    console.log('allSelected', allSelected)
    console.log('individualSelected', individualSelected)
    console.log('selectedEmail', selectedEmail)
    console.log('checked', checked)
    let selectedEmails = this.state.selectedEmails
    if (allSelected && !individualSelected) {
        this.props.emails.forEach((email) => {
          selectedEmails.add(email._id)
        })
    } else if (!allSelected && !individualSelected) {
      selectedEmails.clear()
    } else if (individualSelected) {
      if (checked) {
        selectedEmails.add(selectedEmail)
        if (selectedEmails.size === this.props.emails.length) {
          this.checkAll()
        }
      } else {
        selectedEmails.delete(selectedEmail)
        this.setState({checked})
      }
    }
    this.setState({selectedEmails})
    console.log('selectedEmails', this.state.selectedEmails)
  }
  removeSelected () {
    const selectedEmails = Array.from(this.state.selectedEmails)
    Meteor.call('emails.remove', selectedEmails, (err, result) => {
      if (err) console.log(err)
      if (result) console.log(result)
    })
  }
  checkAll () {
    this.setState({checked: !this.state.checked})
    console.log('chcekedClick', this.state.checked)
    this.handleSelectedEmails(!this.state.checked, false)
  }
  renderList () {
    console.log(this.props)
    return this.props.emails.map(email => {
      // console.log(email)
      const { name, opr, ctr, _id } = email
      const createdAt = email.createdAt.toDateString()
      const link = `/dashboard/emailpreview/${_id}`
      return (
        <EmailListItem
          handleSelectedEmails={this.handleSelectedEmails.bind(this)}
          name={name}
          createdAt={createdAt}
          opr={opr}
          ctr={ctr}
          link={link}
          key={email._id}
          id={email._id}
          value={this.state.checked || this.state.selectedEmails.has(email._id)} />
        )
    })
  }
  render () {
    // TODO: make checks with state
    return (
      <div className="email_list">
        <table>
          <thead>
            <tr>
              <td><input onChange={this.checkAll.bind(this)} type="checkbox" checked={this.state.checked} /></td>
              <td>Title<button onClick={this.removeSelected.bind(this)} className="btn btn-danger">Remove</button></td>
              <td>Dates</td>
              <td>Open Rates</td>
              <td>CTA</td>
            </tr>
          </thead>
          <tbody>
            {this.renderList()}
          </tbody>
        </table>

      </div>
  )
  }
}

export default createContainer(() => {
  Meteor.subscribe('emails')
  return { emails: Emails.find({}).fetch() }
}, EmailList)

和 EmailListItem

import React, { Component } from 'react'
import { Link } from 'react-router'

class EmailListItem extends Component {
  render () {
    console.log('_id', this.props.id)
    return (
      <tr>
        <td><input ref="myCheckbox"
          onChange={(event) => {
            this.props.handleSelectedEmails(false, true, event.target.name, event.target.checked)
          }}
          checked={this.props.value}
          type="checkbox" name={this.props.id} /></td>
        <td><Link to={this.props.link}>{this.props.name}</Link></td>
        <td>{this.props.createdAt}</td>
        <td>Open Rates</td>
        <td>CTA</td>
      </tr>
    )
  }
}

export default EmailListItem

我認為,不需要為每個電子郵件 ID 維護單獨的狀態,您已經將值存儲在parent組件中,將值從parent組件傳遞到props ,另一件事是選擇所有電子郵件 ID,您在parent組件中維護一個 bool,在在 props 中傳遞值的時間檢查 bool,如果 bool 為真則傳遞true否則檢查set並傳遞set返回的結果。

檢查jsfiddle的工作解決方案: https ://jsfiddle.net/h17mcjwa/

試試這個renderList方法:

renderList () {
 return this.props.emails.map(email => {
      const { name, opr, ctr, _id } = email
      const createdAt = email.createdAt.toDateString()
      const link = `/dashboard/emailpreview/${_id}`
      return (
        <EmailListItem
          handleSelectedEmails={this.handleSelectedEmails.bind(this)}
          name={name}
          createdAt={createdAt}
          opr={opr}
          ctr={ctr}
          link={link}
          key={email._id}
          id={email._id} 
          value={this.state.checked || this.state.selectedEmails.has(email._id)}
        />
      )
   })
 }

並使用此組件:

class EmailListItem extends Component {
  constructor (props) {
    super(props)
    //this.state = {
    //  checked: false
    //}
  }

  //checkedClick () {
  //  this.setState({checked: !this.state.checked})
  //  console.log('chcekedClick')
  //}

  //componentDidUpdate () {
  //  if (this.props.selecetedAllEmails) {
  //    this.checkedClick()
  //    this.props.handleSelectedEmails(myCheckbox.name, myCheckbox.checked)
  //  }
  //}

  render () {
    return (
      <tr>
        <td><input ref="myCheckbox"
          onChange={(event) => {
            this.props.handleSelectedEmails(event.target.name, event.target.checked)
          }}
          checked={this.props.value}
          type="checkbox" name={this.props.id} /></td>
        <td><Link to={this.props.link}>{this.props.name}</Link></td>
        <td>{this.props.createdAt}</td>
        <td>Open Rates</td>
        <td>CTA</td>
      </tr>
    )
  }
}

如果它對你不起作用,請告訴我。

您可以使用componentWillReceiveProps而不是componentDidUpdate

class EmailListsItem extends Component {
  // ...
  componentWillReceiveProps (nextProps) {
    const { myCheckbox } = this.refs

    // if selecetedAllEmails is updated from false to true
    if (nextProps.selecetedAllEmails && !this.props.selecetedAllEmails) {
      this.checkedClick()
      this.props.handleSelectedEmails(myCheckbox.name, myCheckbox.checked)
    }
  }
  // ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM