Реакционно-родная панель поиска и проблема flatList

Проблема

В MySQL некоторые слова типа SELECT, INSERT, DELETE и т. д. являются зарезервированными словами. Поскольку они имеют особое значение, MySQL рассматривает его как синтаксическую ошибку всякий раз, когда вы используете их в качестве имени таблицы, имени столбца или другого идентификатора - если вы не окружите идентификатор обратными выводами.

Как отмечено в официальные документы в разделе 10.2 Имена объектов схемы (выделено мной):

Определенные объекты в MySQL, включая базу данных, таблицу, индекс, столбец, псевдоним, хранимые процедуры, разделы, табличное пространство и другие имена объектов известны как идентификаторы .

...

Если идентификатор содержит специальные символы или является зарезервированное слово , вы должны ссылаться на него всякий раз, когда вы ссылаетесь на него.

...

Символ кавычки идентификатора - это backtick ("`"):

blockquote>

Полный список ключевых слов и зарезервированных слов можно найти в разделе 10.3 Ключевые слова и зарезервированные слова . На этой странице слова, за которыми следует «(R)», являются зарезервированными словами. Некоторые зарезервированные слова перечислены ниже, в том числе многие, которые имеют тенденцию вызывать эту проблему.

  • ADD
  • AND
  • ПЕРЕД
  • BY
  • CALL
  • CASE
  • CONDITION
  • DELETE
  • DESC
  • DESCRIBE
  • FROM
  • GROUP
  • IN
  • INDEX
  • INSERT
  • INTERVAL
  • IS
  • KEY
  • LIKE
  • LIMIT
  • LONG
  • MATCH
  • NOT
  • OPTION
  • OR
  • ORDER
  • PARTITION
  • ССЫЛКИ
  • SELECT
  • TABLE
  • TO
  • UPDATE
  • ГДЕ

Решение

У вас есть два варианта.

1. Не используйте зарезервированные слова в качестве идентификаторов

. Простейшим решением является просто избегать использования зарезервированных слов в качестве идентификаторов. Возможно, вы найдете другое разумное имя для своего столбца, который не является зарезервированным словом.

У этого есть несколько преимуществ:

  • Это исключает возможность того, что вы или другое разработчик, использующий вашу базу данных, случайно напишет синтаксическую ошибку из-за забывания или не зная, что конкретный идентификатор является зарезервированным словом. В MySQL много зарезервированных слов, и большинство разработчиков вряд ли узнают их все. Не используя эти слова в первую очередь, вы избегаете оставлять ловушки для себя или будущих разработчиков.
  • Средства цитирования идентификаторов различаются между диалектами SQL. Хотя MySQL использует обратные ссылки для цитирования идентификаторов по умолчанию, ANSI-совместимый SQL (и, действительно, MySQL в режиме ANSI SQL, как указано здесь ) использует двойные кавычки для цитирования идентификаторов. Таким образом, запросы, которые цитируют идентификаторы с backticks, менее легко переносятся на другие диалекты SQL.

Чисто ради снижения риска будущих ошибок это обычно более разумный курс действий, чем backtick-quoting идентификатор.

2. Использовать backticks

Если переименование таблицы или столбца невозможно, оберните идентификатор оскорбления в backticks (`), как описано в более ранней цитате из 10.2 Имена объектов схемы .

Пример демонстрации использования (взято из 10.3 Ключевые слова и зарезервированные слова ):

mysql> CREATE TABLE interval (begin INT, end INT);
ERROR 1064 (42000): You have an error in your SQL syntax.
near 'interval (begin INT, end INT)'

mysql> CREATE TABLE `interval` (begin INT, end INT);
Query OK, 0 rows affected (0.01 sec)
blockquote>

Аналогично, запрос из вопроса можно устранить, обернув ключевое слово key в обратные ссылки, как показано ниже:

INSERT INTO user_details (username, location, `key`)
VALUES ('Tim', 'Florida', 42)";               ^   ^

2
задан Jasmine Wong 4 March 2019 в 18:59
поделиться

1 ответ

1127 Это действительно хорошее начало. Однако есть несколько проблем с вашим кодом. Итак, давайте пройдемся по нему и посмотрим, где мы можем сделать некоторые улучшения.

Конструктор

Во-первых, в своем конструкторе вы делаете данные объектом, а не массивом. Плоские списки не работают с объектами, которые они работают с массивами, поэтому это немедленно вызовет у вас проблемы. Вы действительно должны удалить {} из-за restaurantList.

constructor() {
    super();
    this.state = {
        loading: false,
        data: {restaurantList}, // You shouldn't have {} around the restaurantList
        error: null,
    };
    this.arrayholder = []; // we also don't need this
}

Вы должны обновить свой конструктор до этого

constructor (props) {
  super(props);

  this.state = {
    loading: false,
    data: restaurantList, // notice we have no {} around restaurantList
    error: null,
    value: ''
  };
}

renderHeader

В вашей функции renderHeader вы используете onChange, а не onChangeText. onChange возвращает объект, но вы хотите, чтобы text было помещено в строку поиска. Вам нужно обновить функцию renderHeader, чтобы она была такой.

renderHeader = () => {
  return (
    <SearchBar
      placeholder="Type..."
      value={this.state.value}
      onChangeText={text => this.searchFilterFunction(text)} // now we are using the correct function to capture the text
    />
  );
};

searchFilterFunction

Есть несколько проблем с этой функцией. Сначала вы смотрите на this.arrayholder, который пуст. На самом деле нам не нужен дополнительный массив для хранения данных, так как мы можем просто использовать restaurantList, который мы импортировали ранее. Во-вторых, вы используете indexOf для строки, лучше использовать includes.

searchFilterFunction = text => {
  this.setState({
    value: text
  });

  const newData = restaurantList.filter(item => {
    const itemData = `${item.name.toUpperCase()} ${item.type.toUpperCase()}`;
    const textData = text.toUpperCase();
    return itemData.includes(textData); // this will return true if our itemData contains the textData
  });

  this.setState({
    data: newData
  });
};

FlatList

В вашем FlatList вы должны использовать реквизит extraData, поскольку это позволит FlatList обновляться при изменении базовых данных. Вы также должны добавить keyExtractor.

<FlatList
  keyExtractor={(item, index) => `${index}`}
  extraData={this.state} // <- add this prop
  data={this.state.data}
  renderItem={({ item }) => (
    <Text>{item.name} {item.type}</Text>
  )}
  ItemSeparatorComponent={this.renderSeparator}
  ListHeaderComponent={this.renderHeader}
/>

Собираем все вместе

Так что, если мы соберем все это вместе, добавим макет данных, чтобы мы могли проверить, работает ли он. Мы должны получить что-то вроде этого.

// mock the data as you didn't provide an example
const restaurantList = [
  {
    type: 'Italian',
    name: 'DiMaggio'
  },
  {
    type: 'Greek',
    name: 'Athena'
  }
];

export default class SearchScreen extends React.Component {
  static navigationOptions = {
    title: 'Search for Restaurants'
  };
  constructor (props) {
    super(props);

    this.state = {
      loading: false,
      data: restaurantList,
      error: null,
      value: ''
    };
  }

  renderSeparator = () => {
    return (
      <View
        style={{
          height: 1,
          width: '86%',
          backgroundColor: '#CED0CE',
          marginLeft: '14%'
        }}
      />
    );
  };

  searchFilterFunction = text => {
    this.setState({
      value: text
    });

    const newData = restaurantList.filter(item => {
      const itemData = `${item.name.toUpperCase()} ${item.type.toUpperCase()}`;
      const textData = text.toUpperCase();
      return itemData.includes(textData);
    });

    this.setState({
      data: newData
    });
  };

  renderHeader = () => {
    return (
      <SearchBar
        placeholder="Type..."
        value={this.state.value}
        onChangeText={text => this.searchFilterFunction(text)}
      />
    );
  };

  render () {
    if (this.state.loading) {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <ActivityIndicator />
        </View>
      );
    } else {
      return (
        <View style={styles.container}>
          <FlatList
            keyExtractor={(item, index) => `${index}`}
            extraData={this.state}
            data={this.state.data}
            renderItem={({ item }) => (
              <Text>{item.name} {item.type}</Text>
            )}
            ItemSeparatorComponent={this.renderSeparator}
            ListHeaderComponent={this.renderHeader}
          />
        </View>
      );
    }
  }
}

Закуска

Вы можете увидеть, как он работает на следующем перекусе https://snack.expo.io/@andypandy/flatlist-with-search [ 1134]

0
ответ дан Andrew 4 March 2019 в 18:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: