[英]How to filter data in ListView React-native?
I am trying to filter my array object list and then trying to display in the ListView with new DataSource. 我试图过滤我的数组对象列表,然后尝试使用新的DataSource在ListView中显示。 However, the list is not getting filtered.
但是,列表未被过滤。 I know that my filter function works correctly.
我知道我的过滤功能正常工作。 ( I checked it in the console.log )
(我在console.log中查了一下)
I am using Redux to map my state to prop. 我正在使用Redux将我的状态映射到prop。 And then trying to filter the prop.
然后尝试过滤道具。 Is this the wrong way?
这是错误的方式吗?
Here is my code: 这是我的代码:
/*global fetch:false*/
import _ from 'lodash';
import React, { Component } from 'react';
import { ListView, Text as NText } from 'react-native';
import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import {
Container, Header, Item,
Icon, Input, ListItem, Text,
Left, Right, Body, Button
} from 'native-base';
import Spinner from '../common/Spinner';
import HealthImage from '../misc/HealthImage';
import { assetsFetch } from '../../actions';
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
class AssetsList extends Component {
componentWillMount() {
this.props.assetsFetch();
// Implementing the datasource for the list View
this.createDataSource(this.props.assets);
}
componentWillReceiveProps(nextProps) {
// Next props is the next set of props that this component will be rendered with.
// this.props is still equal to the old set of props.
this.createDataSource(nextProps.assets);
}
onSearchChange(text) {
const filteredAssets = this.props.assets.filter(
(asset) => {
return asset.name.indexOf(text) !== -1;
}
);
this.dataSource = ds.cloneWithRows(_.values(filteredAssets));
}
createDataSource(assets) {
this.dataSource = ds.cloneWithRows(assets);
}
renderRow(asset) {
return (
<ListItem thumbnail>
<Left>
<HealthImage health={asset.health} />
</Left>
<Body>
<Text>{asset.name}</Text>
<NText style={styles.nText}>
Location: {asset.location} |
Serial: {asset.serial_number}
</NText>
<NText>
Total Samples: {asset.total_samples}
</NText>
</Body>
<Right>
<Button transparent onPress={() => Actions.assetShow()}>
<Text>View</Text>
</Button>
</Right>
</ListItem>
);
}
render() {
return (
<Input
placeholder="Search"
onChangeText={this.onSearchChange.bind(this)}
/>
<ListView
enableEmptySections
dataSource={this.dataSource}
renderRow={this.renderRow}
/>
);
}
}
const mapStateToProps = state => {
return {
assets: _.values(state.assets.asset),
spinner: state.assets.asset_spinner
};
};
export default connect(mapStateToProps, { assetsFetch })(AssetsList);
What am I doing wrong here? 我在这做错了什么?
It's a little hard to follow what's going on here. 跟踪这里发生的事情有点困难。 I would simplify it to be like so:
我会简化它是这样的:
class AssetsList extends Component {
state = {};
componentDidMount() {
return this.props.assetsFetch();
}
onSearchChange(text) {
this.setState({
searchTerm: text
});
}
renderRow(asset) {
return (
<ListItem thumbnail>
<Left>
<HealthImage health={asset.health} />
</Left>
<Body>
<Text>{asset.name}</Text>
<NText style={styles.nText}>
Location: {asset.location} |
Serial: {asset.serial_number}
</NText>
<NText>
Total Samples: {asset.total_samples}
</NText>
</Body>
<Right>
<Button transparent onPress={() => Actions.assetShow()}>
<Text>View</Text>
</Button>
</Right>
</ListItem>
);
}
getFilteredAssets() {
}
render() {
const filteredAssets = this.state.searchTerm
? this.props.assets.filter(asset => {
return asset.name.indexOf(this.state.searchTerm) > -1;
})
: this.props.assets;
const dataSource = ds.cloneWithRows(filteredAssets);
return (
<Input
placeholder="Search"
onChangeText={this.onSearchChange.bind(this)}
/>
<ListView
enableEmptySections
dataSource={dataSource}
renderRow={this.renderRow}
/>
);
}
}
const mapStateToProps = state => {
return {
assets: _.values(state.assets.asset),
spinner: state.assets.asset_spinner
};
};
export default connect(mapStateToProps, { assetsFetch })(AssetsList);
A few points: 几点:
assetFetch
, so you probably should return it in componentDidMount
. assetFetch
中有异步,所以你可能应该在componentDidMount
返回它。 componentWillMount
to componentDidMount
. componentWillMount
更改为componentDidMount
。 It's recommended to put async fetching componentDidMount
. componentDidMount
。 This can matter if you ever do server side rendering. One thing I have a little concern with is the pattern of fetching inside a component, putting it in global state, and then relying on that component to react to the global state change. 我有点担心的一件事是在组件内部获取模式,将其置于全局状态,然后依靠该组件来响应全局状态变化。 Thus changing global state becomes a side effect of simply viewing something.
因此,改变全球状态成为简单地观察某事物的副作用。 I assume you are doing it because
assets
is used elsewhere, and this is a convenient point to freshen them from the server so that they will show up in other components that do not fetch them. 我假设您正在这样做,因为
assets
在其他地方使用,这是一个方便的点,从服务器刷新它们,以便它们将显示在其他不提取它们的组件中。 This pattern can result in hard-to-find bugs. 这种模式可能导致难以发现的错误。
You need to do setState
to trigger render. 您需要执行
setState
来触发渲染。 Here's how I would do it - 这是我将如何做到的 -
constructor(props) {
super(props);
this.ds = new ListView.DataSource({ rowHasChanged: (r1,r2) => r1 !== r2 });
this.state = {
assets: []
};
}
componentWillMount() {
this.props.assetsFetch();
this.setState({
assets: this.props.assets
});
}
componentWillReceiveProps(nextProps) {
this.setState({
assets: nextProps.assets
});
}
onSearchChange(text) {
const filteredAssets = this.props.assets.filter(asset => asset.name.indexOf(text) !== -1);
this.setState({
assets: _.values(filteredAssets)
});
}
render() {
...
<ListView
dataSource={this.ds.cloneWithRows(this.state.assets)}
.....
/>
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.