I have a table that displays contacts and I want to sort the contacts by first name. The contacts array comes from the redux store, which will come then come through the props, but I want the local state to hold how those contacts are sorted, since it's local UI state. How do I achieve this? I so far have placed contacts into componentWillReceiveProps
but for some reason it doesn't receive the props when it changes. How do I update the local state each time the redux store state changes?
const Table = React.createClass({
getInitialState () {
return {contacts: []}
},
componentWillReceiveProps () {
this.setState({ contacts: this.props.data.contacts})
},
sortContacts (parameter, e){
...
},
render () {
return (
<table>
<thead>
<tr>
<th onClick={this.sortContacts.bind(this, "firstName")}>First Name</th>
</tr>
</thead>
<tbody>
{contactRows}
</tbody>
</table>
)
}
})
update of current code that includes filtering
import React, {Component} from 'react'
import TableRow from './TableRow'
class Table extends Component {
constructor (props) {
super(props)
this.state = { sortBy: "fistName" }
}
sortContacts (parameter) {
console.log('in sortContacts')
this.setState({ sortBy: parameter })
}
sortedContacts () {
console.log('in sortedContacts')
const param = this.state.sortBy
return (
this.props.data.contacts.sort(function (a, b){
if (!a.hasOwnProperty(param)){
a[param] = " ";
}
if (!b.hasOwnProperty(param)){
b[param] = " ";
}
const nameA = a[param].toLowerCase(), nameB = b[param].toLowerCase();
if (nameA > nameB) {
return 1;
} else {
return -1;
}
})
)
}
filteredSortedContacts () {
console.log('in filteredSortedContacts')
const filterText = this.props.data.filterText.toLowerCase()
let filteredContacts = this.sortedContacts()
if (filterText.length > 0) {
filteredContacts = filteredContacts.filter(function (contact){
return (
contact.hasOwnProperty('lastName') &&
contact.lastName.toLowerCase().includes(filterText)
)
})
}
return filteredContacts
}
contactRows () {
console.log('in contactRows')
return this.filteredSortedContacts().map((contact, idx) =>
<TableRow contact={contact} key={idx}/>
)
}
render () {
return (
<div className="table-container">
<table className="table table-bordered">
<thead>
<tr>
<th className="th-cell" onClick={this.sortContacts.bind(this, "firstName")}>First Name</th>
<th onClick={this.sortContacts.bind(this, "lastName")}>Last Name</th>
<th>Date of Birth</th>
<th>Phone</th>
<th>Email</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
{this.contactRows()}
</tbody>
</table>
</div>
)
}
}
export default Table
The issue I'm seeing now is that contactRows, filteredSortedContacts, sortedContacts
are being called multiple times, once for each TableRow. I don't see how this can be happening if I'm only calling contactRows
once in the body.