React native list view search

Umas das vantagens do React é podermos criar nossos próprios componentes e reutilizá-los onde quisermos. Hoje vamos mostrar como fazer um componente de busca em uma listview agrupada. Como de custume, vamos nos basear no projeto criado nesse post

Feito isso, vamos criar um arquivo chamado ListViewSearch.js no mesmo local do arquivo App.js. Esse arquivo é nosso componente e deve ter esse conteúdo:

import React, { Component, } from 'react';
import {
  StyleSheet,
  Text,
  TextInput,
  View,
  ListView,
  TouchableHighlight
} from 'react-native';
	ype DataItem = {
  title: string;
  description: string;
}
const ds = new ListView.DataSource({
  rowHasChanged: (r1, r2) => r1 !== r2,
  sectionHeaderHasChanged: (h1, h2) => h1 !== h2,
});
export default class ListViewSearch extends Component {
  
  constructor(props) {
    super(props);    
    (this: any).renderRow = this.renderRow.bind(this);
    (this: any).renderSeparator = this.renderSeparator.bind(this);
    (this: any).renderSectionHeader = this.renderSectionHeader.bind(this);
    
    this.state = {
      filter: ''
    }
  }
    
  _changeFilter(text){
    this.setState({...this.state,filter:text});
  }     
    
  filterDatasource(text){
        const safe = String(text || '').replace(/([.*^$+?!(){}[]/])/g,'$1');
        const regex = new RegExp(safe, 'i');
        const filter = (row) => regex.test(row.title) || regex.test(row.description);
        
        var out = {};
        for(var sectionID in this.props.dataObject){
            if(!this.props.dataObject.hasOwnProperty(sectionID)){
                continue;
                }
          out[sectionID] = this.props.dataObject[sectionID].data.filter(filter);
        }
      
        return ds.cloneWithRowsAndSections(out);
  }     
    
  render() {
    const dataSource = this.filterDatasource(this.state.filter);
    
    return (
      <View style={styles.container}>
          <View style={styles.searchContainer}>
          <TextInput
                  style={styles.searchInput}
            autoCapitalize="none"
            autoCorrect={false}
            clearButtonMode="always"
            onChangeText={(filter) => this._changeFilter(filter)}
                      value={this.state.filter}
            placeholder={this.props.filterText}            
            testID="explorer_search"
          />
          </View>
          <ListView
              style={styles.list}
          dataSource={dataSource}
          renderRow={this.renderRow}
              renderSectionHeader={this.renderSectionHeader}
              renderSeparator={this.renderSeparator}
          enableEmptySections={true}
        />
      </View>
    );
  }
  
  renderSectionHeader(sectionData: Array<DataItem>, sectionID: string): ?ReactElement<any> {
    const section = this.props.dataObject[sectionID];
    const sectionStyle = {
        borderBottomColor: section.color
    }
      const isEmpty = !sectionData || sectionData.length <1; 
      let emptyContent;
        if(isEmpty){
          emptyContent = <Text style={styles.sectionEmpty}>{this.props.emptText}</Text>
    }
    return (
      <View>
        <View style={[styles.sectionContainer, sectionStyle]}>
          <Text style={[styles.sectionHeader, sectionStyle]}>
            {section.title}
          </Text>
          <View style={[styles.sectionDetail, sectionStyle]} />          
        </View>   
          {emptyContent}
        </View>      
    );
  }
   renderRow(data: DataItem): ?ReactElement<any> {
    let handler = () => {
     console.log(data);
    }
    return (
      <View>
        <TouchableHighlight onPress={handler}>
          <View style={styles.row}>
            <Text style={styles.rowTitle}>
              {data.title}
            </Text>
            <Text style={styles.rowDescription}>
              {data.description}
            </Text>
          </View>
        </TouchableHighlight>
      </View>
    );
  }
  renderSeparator(sectionID: string, rowID: any, adjacentRowHighlighted: boolean): ?ReactElement<any> {    
    return (
      <View key={`${sectionID}-${rowID}`} style={styles.separator} />
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop:25,
    backgroundColor: '#fff'
   },
   list: {
    backgroundColor: '#eeeeee',
   },
     sectionContainer: {
    backgroundColor: '#fff',
        borderBottomWidth: 1,
        height: 50, 
        justifyContent: 'flex-end'        
   },
     sectionHeader:{
        paddingLeft: 15,
        fontWeight: 'bold',
        fontSize: 16,
     },
     sectionDetail:{
        borderBottomWidth: 4,
        width: 120
     },
     sectionEmpty:{
            backgroundColor: '#fff',
            paddingHorizontal: 15,
        paddingVertical: 8,
     },
   row: {
    backgroundColor: 'white',
    paddingHorizontal: 15,
    paddingTop: 25,
   },
   rowTitle: {
    fontSize: 14,
    fontWeight: '500',
   },
   rowDescription: {
    fontSize: 14,
    color: '#888888',
    lineHeight: 20,
   },
   separator: {
    height: StyleSheet.hairlineWidth,
    backgroundColor: '#bbbbbb',
    marginLeft: 15,
   },
     searchContainer: {
    backgroundColor: '#FFF',
        paddingVertical: 10,
        borderBottomWidth: StyleSheet.hairlineWidth,
        borderBottomColor: '#bbbbbb',
   },
   searchInput: {
    backgroundColor: 'white',
    paddingLeft: 20,
    height: 35,
  },
});

Agora no arquivo App.js vamos editar para ficar desse jeito:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */
import React, { Component, } from 'react';
import ListViewSearch from './ListViewSearch';
import {
  View
} from 'react-native';
const sections = {
  JQ_MOBILE: {
    color: '#90CAF9',
    title: 'Jquery Mobile',
    data: [
      {
          title: 'Framework UI',
          description: 'framework destinado ao desenvolvimento de toda a interface gráfica de soluções móveis para a web'
        },
        {
          title: 'Multi-plataforma',
          description: ' resultado obtido em diferentes dispositivos de diferentes plataformas operacionais'
        },
        {
          title: 'Híbrido',
          description: 'A solução híbrida, como o nome sugere, é intermediária e flutua entre uma realidade '
        },
        {
          title: 'Theme Roller',
          description: 'Uma ferramenta bem útil para criação de novos temas é o Theme Roller'
        },
        {
          title: 'Ajax',
          description: 'Baseada na biblioteca jQuery, de onde reaproveita técnicas de manipulação de eventos e requisições Ajax'
        },
        {
          title: 'Fácil',
          description: 'biblioteca poderosa e de fácil utilização para a construção de interfaces web com o usuário'
        }
    ]
  },
  REACT_JS: {
    color: '#FFA726',
    title: 'ReactJS',
    data:[
     {
        title: 'Componentes',
        description: 'React é uma ferramenta somente para criar componentes'
      },
      {
        title: 'Nasceu no instagram',
        description: 'Criada pela equipe do instagram (isso mesmo, antes do facebook comprar)'
      },
      {
        title: 'Virtual-DOM',
        description: 'v-dom é uma técnica simples e complexa ao mesmo tempo. Simples no conceito e complexa na aplicação.'
      }
    ]
  },
  REACT_NATIVE: {
    color: '#9CCC65',
    title: 'React Native',
    data:[
      {
        title: 'Híbrido',
        description: ' geração de aplicativos nativos através de código híbrido'
      },
      {
        title: 'Nativo',
        description: 'Quando a framework gera os aplicativos Android e iOS, ela converte este código híbrido para código nativo'
      },
      {
        title: 'Deploy rápido',
        description: 'Através de uma ferramenta chamada Expo ele permite que o usuário rode um servidor local na máquina e acesse o aplicativo em seu celular ou emulador através da url deste servidor'
      }
    ]
  },
}
export default class App extends Component {
  
  render() {
    
    return (
      <ListViewSearch 
      dataObject={sections}
      filterText={'Procurar...'}
      emptText={'Não existem dados para o filtro informado'}
      />
    );
  }
  
}

Percebe-se que montamos nosso objeto com os registros e passamos como propriedade para o componente.

Dessa forma nosso componente pode ser reutilizado em qualquer projeto:

Imagem

Segue a documentação oficial: https://facebook.github.io/react-native/docs/listviewdatasource.html

Comentários

 

Quem Sou

Graduado em ADS (Análise e desenvolvimento de sistemas).

Não sou "devoto" de nenhuma linguagem de programação. Procuro aproveitar o melhor de cada uma de acordo com a necessidade do projeto. Prezo por uma arquitetura bem feita, código limpo, puro e simples! 

anuncio atendente