2

反応ネイティブで検索およびフィルタリング バーを実装しようとしていますが、DataSource オブジェクトの操作方法がよくわかりません。データは JSON 形式であり、次のことを行う必要があります。

  • クエリ文字列に基づく提供された JSONの全文検索
  • タグベースのフィルタリング、トークンとして提供されるタグを使用

これはRNPlay (Link)の非常に簡単な例です。

反応ネイティブ内で検索およびフィルタリング機能を実装する方法は?

import React, {Component} from 'react';
import { AppRegistry, View, ListView, Text, TextInput, StyleSheet, TouchableOpacity } from 'react-native';

const FILTERS = [
        {
          tag: "clever", active: false
        }, {
          tag: "scary", active: false
        }, {
          tag: "friendly", active: false
        }, {
          tag: "obedient", active: false
        }
      ];

const FIELDS = [
        {
          title:"Dog",
          subtitle: "Bulldog",
          tags: [ { tag: "clever" }, { tag: "scary" } ]
        }, {
          title:"Cat",
          subtitle:"Persian cat",
          tags: [ { tag: "friendly" }, { tag: "obedient" } ]
        }, {
          title:"Dog",
          subtitle:"Poodle",
          tags: [ { tag: "obedient" } ]
        }
      ];

class SampleApp extends Component {

  constructor(props) {
    super(props);
    var ds = new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
    });
    var ds2 = new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1.active !== row2.active,
    });
    this.state = {
      dataSource: ds.cloneWithRows(FIELDS),
      dataSource2: ds2.cloneWithRows(FILTERS),
      filters: FILTERS,
    };
  }

  renderFilter(filter) {
    return (
        <TouchableOpacity onPress={this.handleClick.bind(this, filter)}>
            <Text style={{fontSize: 24, backgroundColor:(filter.active)?'red':'grey', margin:5}}>{filter.tag}</Text>
      </TouchableOpacity>
    ); 
  }

  renderField(field) {
    return (
      <View style={{flexDirection:'column', borderWidth: 3, borderColor: 'yellow'}}>
        <Text style={{fontSize: 24}}>{field.title}</Text>
        <Text style={{fontSize: 24}}>{field.subtitle}</Text>
        {field.tags.map((tagField) => {
          return (
            <View style={{backgroundColor:'blue'}}>
              <Text style={{fontSize: 24}}>{tagField.tag}</Text>
            </View>
          );
        })}
      </View>
    );
  }

  handleClick(filter) {
    const newFilters = this.state.filters.map(a => {
      let copyA = {...a};
      if (copyA.tag === filter.tag) {
        copyA.active = !filter.active;
      }
      return copyA;
    });
    this.setState({
      dataSource2: this.state.dataSource2.cloneWithRows(newFilters),
      filters: newFilters
    }); 
  }

  setSearchText(event) {
   let searchText = event.nativeEvent.text;
   this.setState({searchText});
  }

  render() {
    return (
      <View>
        <TextInput
                    style={styles.searchBar}
                    value={this.state.searchText}
                    onChange={this.setSearchText.bind(this)}
                    placeholder="Search" />
        <ListView
          style={{flexDirection:'row', flex:1, flexWrap:'wrap'}}
          horizontal={true}
          dataSource={this.state.dataSource2}
          renderRow={this.renderFilter.bind(this)}
        />
        <ListView
          dataSource={this.state.dataSource}
          renderRow={this.renderField.bind(this)}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  searchBar: {
    marginTop: 30,
    fontSize: 40,
    height: 50,
    flex: .1,
    borderWidth: 3,
    borderColor: 'red',
  },
});

AppRegistry.registerComponent('SampleApp', () => SampleApp);
4

1 に答える 1