大家好,我有这个模块
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执行检查,如果选中了全局复选框,那么我也会检查该项目。但这会导致无限循环。请问这里最好的解决方案是什么? 提前谢谢大家!
答案 0 :(得分:5)
虽然一些答案提供了选择所有复选框的特定功能,但我还需要常见功能,例如取消选择全部,选择全部然后取消选择一些,当手动选择所有选择所有框检查时...等等我写了所有这些并将其作为答案发布在这里。感谢所有回复的人。此代码基于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
答案 1 :(得分:3)
我认为,不需要为每个电子邮件ID维护个别状态,您已将值存储在parent
组件中,从parent
中的props
传递值,其他的是为了选择所有的电子邮件ID,你在父母中保持一个bool,在传递道具值时检查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>
)
}
}
如果它对你不起作用,请告诉我。
答案 2 :(得分:1)
您可以使用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)
}
}
// ...
}