我创建了一个对HTML表格进行排序和过滤的组件。该功能是正确的,但是我的表在显示“未找到资产记录”。时出现问题。但是,当我单击其中一个标头时,它会以状态显示数据数组的内容。我确实对这种奇怪的行为感到困惑和困惑。我认为问题可能出在filterAssets
函数上,因为如果我对此进行更改:
let filterAssets = this.state.data.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
})
对此:
let filterAssets = this.props.assetManagement.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
})
如果有帮助,请参见以下代码
import React, { Component, Fragment } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { getAssetManagement } from '../../actions/asset-management'
class AssetManagement extends Component {
static propTypes = {
assetManagement: PropTypes.array.isRequired,
getAssetManagement: PropTypes.func.isRequired
}
componentDidMount() {
this.props.getAssetManagement()
}
state = {
name: '',
search: '',
data: []
}
sortBy = this.sortBy.bind(this)
compareBy = this.compareBy.bind(this)
onSubmit = e => {
e.preventDefault()
}
onChange = e =>
this.setState({
[e.target.name]: e.target.value
})
updateSearch = e =>
this.setState({
search: e.target.value.substr(0, 20)
})
compareBy(key) {
return (a, b) => {
if (a[key] < b[key]) return -1
if (a[key] > b[key]) return 1
return 0
}
}
sortBy(key) {
let arrayCopy = [...this.props.assetManagement]
this.state.data.sort(this.compareBy(key))
this.setState({ data: arrayCopy })
}
render() {
let filterAssets = this.state.data.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
})
return (
<Fragment>
{/* Search input */}
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text btn-secondary">
<i class="fas fa-search" />
</span>
</div>
<input
className="form-control"
type="text"
placeholder="Search Asset"
onChange={this.updateSearch.bind(this)}
value={this.state.search}
/>
</div>
{/* Asset management table */}
<div className="table-responsive">
<table className="table table-bordered text-center">
<thead>
<tr>
<th onClick={() => this.sortBy('id')}>ID</th>
<th onClick={() => this.sortBy('name')}>Name</th>
</tr>
</thead>
<tbody>
{filterAssets != 0 ? (
filterAssets.map(a => (
<tr key={a.id}>
<td>{a.id}</td>
<td>{a.name}</td>
</tr>
))
) : (
<tr>
<td colSpan={6}>No asset records found.</td>
</tr>
)}
</tbody>
</table>
</div>
</Fragment>
)
}
}
const mapStateToProps = state => ({
assetManagement: state.assetManagement.assetManagement
})
export default connect(
mapStateToProps,
{ getAssetManagement }
)(AssetManagement)
答案 0 :(得分:1)
这里真正的问题是,您有两个数据源:state.data
和props.assetManagement
-从redux检索并从props.assetManagement
获取最新数据,但是当您需要触发排序,您将复制到state.data
。然后出现问题,因为直到触发props.assetManagement
函数,您才从state.data
复制到sortBy
。
一个解决方案是摆脱state.data
并将排序键存储在状态中。您可以更新,重置该键值,并且排序逻辑仅应应用于props.assetManagement
:
class AssetManagement extends Component {
static propTypes = {
assetManagement: PropTypes.array.isRequired,
getAssetManagement: PropTypes.func.isRequired
}
componentDidMount() {
this.props.getAssetManagement()
}
state = {
name: '',
search: '',
sortingKey: ''
}
sortBy = this.sortBy.bind(this)
compareBy = this.compareBy.bind(this)
onSubmit = e => {
e.preventDefault()
}
onChange = e =>
this.setState({
[e.target.name]: e.target.value
})
updateSearch = e =>
this.setState({
search: e.target.value.substr(0, 20)
})
compareBy(key) {
return (a, b) => {
if (a[key] < b[key]) return -1
if (a[key] > b[key]) return 1
return 0
}
}
sortBy(key) {
if (key !== this.state.sortingKey) {
this.setState({ sortingKey: key });
}
}
render() {
let sortAssets = !!this.state.sortingKey ?
this.props.assetManagement.sort(this.compareBy(this.state.sortingKey)) :
this.props.assetManagement;
let filterAssets = sortAssets.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
});
return (
<Fragment>
{/* Search input */}
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text btn-secondary">
<i class="fas fa-search" />
</span>
</div>
<input
className="form-control"
type="text"
placeholder="Search Asset"
onChange={this.updateSearch.bind(this)}
value={this.state.search}
/>
</div>
{/* Asset management table */}
<div className="table-responsive">
<table className="table table-bordered text-center">
<thead>
<tr>
<th onClick={() => this.sortBy('id')}>ID</th>
<th onClick={() => this.sortBy('name')}>Name</th>
</tr>
</thead>
<tbody>
{filterAssets != 0 ? (
filterAssets.map(a => (
<tr key={a.id}>
<td>{a.id}</td>
<td>{a.name}</td>
</tr>
))
) : (
<tr>
<td colSpan={6}>No asset records found.</td>
</tr>
)}
</tbody>
</table>
</div>
</Fragment>
)
}
}
答案 1 :(得分:0)
将filterAssets != 0
更改为filterAssets.length > 0
第一个渲染器:
let filterAssets = this.state.data.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
})
您的this.state.data
为空,如果正确处理redux,只有this.props.assetManagement
可用,所以也就怪不得从过滤中得到任何东西。
顺便说一句:filterAssets != 0
绝对是错误的,所以请先更改此行。
答案 2 :(得分:0)
在不使用构造函数的情况下对React Component使用替代语法的情况下,您将不再有权使用prop。因此,如果您返回使用标准构造函数,问题就会消失,例如:
21 = 14
22 = 9
11 = 22
12 = 4