2017-03-07 1 views
3

배열 개체의 목록을 필터링 한 다음 새 DataSource로 ListView에 표시하려고합니다. 그러나 목록은 필터링되지 않습니다. 내 필터 기능이 올바르게 작동하는 것 같습니다. (console.log에서 확인)ListView에서 데이터를 필터링하는 방법 React-native?

내 상태를 소품으로 매핑하는 데 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. 귀하의 구성 요소 상태입니다. 구성 요소에만 속하는 상태 즉 검색 용어 하나가 있습니다. 구성 요소 상태로 유지하십시오.
  2. 수명주기 기능에서 데이터 소스를 변경하지 마십시오. 렌더링에서 필요한 최신 지점을 수행하십시오.
  3. assetFetch에 비동기가있는 것 같습니다. 따라서 componentDidMount으로 반환해야합니다.
  4. componentWillMount에서 componentDidMount으로 변경되었습니다. 비동기 가져 오기 componentDidMount을 넣는 것이 좋습니다. 서버 측 렌더링을 수행하는 경우 중요합니다.
  5. 검색어가없는 경우 필터링을 건너 뜁니다. 이것은 목록이 매우 큰 경우에만 중요합니다.

내가 약간의 걱정거리가있는 부분 중 하나는 구성 요소를 전역 상태로 전환 한 다음 해당 구성 요소를 사용하여 전역 상태 변경에 반응하는 패턴입니다. 따라서 글로벌 상태의 변화는 단순히 무언가를 보는 것의 부작용이됩니다. assets이 다른 곳에서 사용되기 때문에 서버에서 새로 고침하여 편리하게 가져올 수 있으므로 가져 오는 다른 구성 요소에 표시됩니다. 이 패턴은 찾기 힘든 버그를 가져올 수 있습니다.

+0

그것은 작동합니다! 정말 고맙습니다!! 내가해야만하는 것은 텍스트의 생성자에서 초기 상태를 설정하는 것이 었습니다. 감사합니다. Tim! –

+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 상황에서이 문제에 접근하는 올바른 방법이 아닙니다. 당신은 내가 액션과 디스패처로 컴포넌트 레벨에서 내 상태를 처리하는 방식을 바꾸라고 요청하고 있습니다. –

관련 문제