2017-03-07 14 views
3

配列オブジェクトのフィルタをフィルタリングしてから、新しいDataSourceでListViewに表示しようとしています。ただし、リストはフィルタリングされません。私は私のフィルタ機能が正しく動作することを知っています。 (私はconsole.logで確認しました)ListViewでデータをフィルタリングする方法React-native?

私は自分の状態をpropにマップするのにReduxを使用しています。そして、小道具をろ過しようとしています。これは間違った方法ですか?ここで

は私のコードです:私はここで間違って

/*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); 

何をしているのですか?

答えて

5

ここで起こっていることに従うのは少し難しいです。

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); 

いくつかのポイント:

  1. あなたのコンポーネントがステートフルである私はそうのようになり、それを単純化します。コンポーネントにのみ属している1つの状態、つまり検索語があります。それをコンポーネントの状態に保ちます。
  2. ライフサイクル機能でデータソースを変更しないでください。レンダリングで必要なことをあなたが知っている最新のポイントにしてください。
  3. assetFetchには非同期のものがあると思いますので、おそらくcomponentDidMountに返す必要があります。
  4. componentWillMountからcomponentDidMountに変更されました。非同期フェッチを行うことをお勧めしますcomponentDidMount。これはサーバー側のレンダリングを行う場合に重要です。
  5. 検索語句がない場合は、フィルタリングをスキップします。これはリストが非常に大きい場合にのみ重要です。

私が少し関心を寄せていることは、コンポーネント内をフェッチし、グローバル状態にしてから、そのコンポーネントを使用してグローバル状態変更に反応するパターンです。したがって、グローバルな状態の変化は、単に何かを見ることの副作用になります。 assetsが他の場所で使用されているため、これを実行していると想定しています。これは、サーバーからフェンスを取得して、フェッチしない他のコンポーネントに表示されるように便利です。このパターンは、見つけにくいバグにつながります。

+0

それは動作します!どうもありがとうございます!!私がしなければならなかったのは、テキストのコンストラクタの初期状態を設定することでした。 :)ティムありがとう! –

+0

ああ、そうです。さもなければ、状態自体は未定義です。それがうれしいです。 –

+0

私は答えを更新しました。コンストラクタの代わりに、私はES7プロパティセッタを使用しました。 –

0

レンダリングをトリガーするには、setStateを実行する必要があります。ここで私はそれをする方法です -

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)} 
    ..... 
    /> 
} 
+0

しかし私はreduxを使って自分の状態を管理しています。これはこれを行う方法だと思いますか?私はreduxのためにコンポーネントレベルから状態を変えることは許されていないと思った。 –

+0

あなたは 'onSearchChange'権利だけに問題がありますか? – vinayr

+0

これは、Reduxの状況でこれを行う正しい方法ではありません。あなたは、私がアクションとディスパッチャーでコンポーネントレベルから私の状態を処理する方法を変更するように私に求めています。 –

関連する問題