Не удается отобразить массив в формате плоского списка - PullRequest
0 голосов
/ 06 августа 2020

Короче говоря, я пытаюсь составить список видеоигр. У меня есть библиотека автозаполнения, которая сопоставляет название игры с тем, что я пишу в поле ввода.

Я добавил кнопку, с помощью которой onPress запускает функцию, которая подталкивает то, что у меня есть в 'запросе' (это то, что я пишу в поле ввода) в массив с именем myGamesArray

Затем я пытаюсь отобразить myGamesArray в форме списка с помощью Flatlist. Но по какой-то причине он не отображается.

Мой код немного запутан, потому что решение, которое я нашел для размещения кнопки рядом с полем ввода, заключалось в изменении направления гибкости на 'row'

Я добавил кнопку прямо под FlatList, чтобы проверить, будет ли она отображаться под полем ввода (что есть), но по какой-то причине плоский список не

Вот все мое приложение. js

/*This is an example of AutoComplete Input/ AutoSuggestion Input*/
import React, { Component } from 'react';
//import react in our code.
import { StyleSheet, Text, TouchableOpacity, View, Image, Alert, FlatList } from 'react-native';
//import all the components we are going to use.
import Autocomplete from 'react-native-autocomplete-input';
import { Button, List, Container, ListItem, Header } from 'native-base';
//import Autocomplete component


//Demo base API to get the data for the Autocomplete suggestion
class App extends Component {
  constructor(props) {
    super(props);
    //Initialization of state
    //games will contain the array of suggestion
    //query will have the input from the autocomplete input
    this.state = {
      myGamesArray: [],
      games: [],
      query: '',
    };
  }
  componentDidMount() {
    //First method to be called after components mount
    //fetch the data from the server for the suggestion
    fetch('https://api.rawg.io/api/games?page=1&platforms=18', {
        "method": "GET",
        "headers": {
          "x-rapidapi-host": "rawg-video-games-database.p.rapidapi.com",
          "x-rapidapi-key": "495a18eab9msh50938d62f12fc40p1a3b83jsnac8ffeb4469f"
        }
      })
      .then(res => res.json())
      .then(json => {
        const { results: games } = json;
        this.setState({ games });
        //setting the data in the games state
      });
  }

  findGame(query) {
    //method called everytime when we change the value of the input
    if (query === '') {
      //if the query is null then return blank
      return [];
    }
 
    const { games } = this.state;
    //making a case insensitive regular expression to get similar value from the game json
    const regex = new RegExp(`${query.trim()}`, 'i');

    //return the filtered game array according the query from the input
    return games.filter(game => game.name.search(regex) >= 0);
  }  

AddItemsToArray=()=>{
 
      //Adding Items To Array.
     this.state.myGamesArray.push( this.state.query.toString() )
 
      // Showing the complete Array on Screen Using Alert (just to check if it's infact inside the array)
      Alert.alert(this.state.myGamesArray.toString());
 
  }
 
  render() {
    const { query } = this.state;
    const games = this.findGame(query);
    const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
 
    return (
      <View>
               
      <View style={styles.container}>
        <Autocomplete
          style={styles.autocompleteContainer1}
          autoCapitalize="none"
          autoCorrect={false}
          //data to show in suggestion
          data={games.length === 1 && comp(query, games[0].name) ? [] : games}
          //default value if you want to set something in input
          defaultValue={query}
          /*onchange of the text changing the state of the query which will trigger
          the findGame method to show the suggestions*/
          onChangeText={text => this.setState({ query: text })}
          placeholder="Selecione os jogos que voce quer receber!"
          renderItem={({ item }) => (
            //you can change the view you want to show in suggestion from here
            //I GET ERROR WHEN TRYING TO ERASE (PS4) IN TEXT BOX ***NEED TO CHECK THIS
            <View style={styles.iconContainer} >
              <TouchableOpacity onPress={() => this.setState({ query: item.name})}
              style={styles.itemContainer} >
              <View>
              <Image
                style={styles.profilepic}
                  source={{uri: item.background_image}}
                />
               </View>
              <Text style={styles.itemText}>
                {item.name} (PS4)
              </Text>
              </TouchableOpacity>
            </View>
          )}
          />
          <Button
            style={styles.addButton}
            icon='plus'
            title="Click Here To Add Value To Array"
            onPress={() => this.AddItemsToArray()}
          />
          <View style={styles.descriptionContainer}>
          
            {games.length > 0 ? (
              //Text inside input box
              <Text style={styles.infoText}>{this.state.query}</Text>
            ) : (
              <Text style={styles.infoText}>{this.state.query}</Text>                    
              )
          } 
          </View>  
      </View>

      <View style={styles.container2}> 
          <Button
          full></Button> 
        
        <FlatList
          data={this.state.myGamesArray}
            renderItem={({ item }) => (
              <ListItem>{item}</ListItem>
            )}
          />
          
    </View>  
      
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: '#fff',
    flex: 1,
    flexDirection:'row',
    padding: 16,
    marginTop: 40,
    justifyContent: 'center',
  },
  container2: {
    backgroundColor: '#fff',
    flex: 1,
    marginTop: 100,
    alignItems: 'center',
    justifyContent: 'center',
  },

  autocompleteContainer1: {
    borderWidth: 1,
    backgroundColor: "#fff",
    borderColor: '#7843FF',
    height: 50,
    width:300
  },
  itemContainer: {
    flex:1,
    flexDirection: 'row',
    borderWidth:0.5,
    borderColor: '#7843FF',
    paddingVertical: 5,
    alignItems: 'center',
    paddingRight: 60
  },
  addButton: {
  width:50,
  height: 50,
  borderColor: '#7843FF',
  borderWidth: 0.5,
  backgroundColor: '#fff'
  },
  descriptionContainer: {
    flex: 1,
    justifyContent: 'center',
    borderRadius: 10,
    color: '#fff',
    borderColor: '#7843FF'
  },
  itemText: {
    fontSize: 15,
    marginLeft: 10,
    marginRight:30,
    marginVertical:10,
    color: '#000',
    textAlign: 'left',
    justifyContent: 'center'
    
  },
  infoText: {
    textAlign: 'center',
    color: '#000',
  },
  profilepic: {
    flex: 3,
    height: 60,
    width: 60,
    marginLeft:10,
    borderRadius: 100,
  },
});
export default App;

1 Ответ

0 голосов
/ 07 августа 2020

Проблема

this.state.myGamesArray.push(this.state.query.toString()) - мутация состояния. Вам нужно на самом деле выполнить обновление состояния и вернуть ссылку на новый объект массива.

Решение

Используйте обновление функционального состояния для доступа к предыдущему объекту состояния и мелкую копию старый массив в новую ссылку на массив и добавьте новое значение запроса в конец.

Кроме того, ведение журнала или иная попытка ссылаться на обновленное состояние сразу после постановки обновления в очередь не будет работать так, состояние равно const и обновил между циклами рендеринга, чтобы он включал текущее состояние.

AddItemsToArray = () => {
  //Adding Items To Array.
  this.setState(prevState => {
      const { myGamesArray, query } = prevState;
      return {
        myGamesArray: [...myGamesArray, query.toString()],
      };
    },
    // Use setState callback to alert with the updated state
    () => {
      // Showing the complete Array on Screen Using Alert (just to check if it's in fact inside the array)
      Alert.alert(this.state.myGamesArray.toString());
    },
  );
}
...