响应本机搜索onChange输入文本,代码结构

时间:2019-09-19 10:33:41

标签: react-native input render onchange setstate

我正在构建一个searchBar,每当进行搜索时,我都会得到未定义的错误,因为直到完成全部值后,状态值才存在,所以我知道我会收到错误,但我无法解决它,所以我尝试根据搜索输入呈现卡,我想我已经对homeScreen进行了硬编码,我不确定我是否做得正确,这是三个if语句是否代表我的一个好习惯的问题。专业吗?我还能做些其他事情使代码更容易阅读和缩短吗?我当时想消除第三个条件,但是如果无法在第二个条件内更改状态,那么我必须添加切换搜索功能,以使其对消除第三个条件的任何想法都可行,如果可以的话..!谢谢大家

homeScreen.js

import axios from 'axios';
import React from 'react';
import {
  ActivityIndicator,
  ScrollView,
  Text,
  View,
  TouchableOpacity,
  TextInput,
} from 'react-native';
import Card from '../Components/Card/card';
export default class HomeScreen extends React.Component {
  state = {
    shows: [],
    isLoading: true,
    search: false,
    title: '',
  };

  componentDidMount() {
    this.getData();
  }
  toggleSearch = () => {
    console.log('hlelleloe');

    this.setState({
      search: true,
    });
  };
  getData = () => {
    const requestUrls = Array.from({length: 9}).map(
      (_, idx) => `http://api.tvmaze.com/shows/${idx + 1}`,
    );

    const handleResponse = data => {
      this.setState({
        isLoading: false,
        shows: data,
      });
    };
    const handleError = error => {
      console.log(error);
      this.setState({
        isLoading: false,
      });
    };

    Promise.all(requestUrls.map(url => axios.get(url)))
      .then(handleResponse)
      .catch(handleError);
  };

  render() {
    const {isLoading, shows, search, title} = this.state;
    if (isLoading) {
      return <ActivityIndicator size="large" color="#0000ff" />;
    } else if (!search) {
      return (
        <View>
          <View>
            <TouchableOpacity
              onPress={this.toggleSearch}
              style={{height: 300, width: 300}}>
              <Text style={{textAlign: 'center', fontSize: 40}}>
                Press to Search
              </Text>
            </TouchableOpacity>
          </View>
          <ScrollView style={{backgroundColor: '#E1E8E7'}}>
            {shows.length &&
              shows.map((show, index) => {
                return (
                  <Card
                    key={show.data.id}
                    title={show.data.name}
                    rating={show.data.rating.average}
                    source={show.data.image.medium}
                    genres={show.data.genres}
                    language={show.data.language}
                    network={show.data.network}
                    schedule={show.data.schedule}
                    summary={show.data.summary}
                    navigation={this.props.navigation}
                  />
                );
              })}
          </ScrollView>
        </View>
      );
    } else if (search) {
      console.log(title);

      return (
        <View>
          <TextInput
            style={{
              height: 100,
              width: 100,
              borderColor: 'gray',
              borderWidth: 1,
            }}
            onChangeText={searchedTitle => (
              <Card title={shows.data.searchedTitle} />
            )}
          />
        </View>
      );
    }
  }
}

Card.js

import React from 'react';
import {
  Image,
  View,
  Text,
  Button,
  StyleSheet,
  TouchableOpacity,
} from 'react-native';
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
import Icon from 'react-native-vector-icons/FontAwesome';

const Card = props => {
  return (
    <View style={styles.container}>
      <Image style={styles.Image} source={{uri: `${props.source}`}} />
      <Text style={styles.title}>{props.title}</Text>
      <View style={styles.ratingContainer}>
        <Text style={styles.rating}>Rating: {props.rating}</Text>
        <Icon name="star" size={30} color="grey" />
      </View>
      <TouchableOpacity
        style={styles.button}
        onPress={() => {
          props.navigation.navigate('Details', {
            title: props.title,
            rating: props.rating,
            source: props.source,
            genres: props.genres,
            language: props.language,
            network: props.network,
            schedule: props.schedule,
            summary: props.summary,
          });
        }}>
        <Text style={styles.buttonText}>Press for details </Text>
      </TouchableOpacity>
    </View>
  );
};

export default Card;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
  },
  Image: {
    flex: -1,
    width: wp('90%'),
    height: hp('65%'),
  },
  title: {
    flex: 1,
    fontSize: 40,
    borderRadius: 10,
    color: '#3C948B',
    margin: 15,
    justifyContent: 'center',
    alignItems: 'center',
  },
  ratingContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: 'white',
    elevation: 6,
    justifyContent: 'space-between',
    borderWidth: 1,
    width: 300,
  },
  rating: {
    fontSize: 25,
    paddingLeft: 15,
  },
  button: {
    flex: 1,
    color: '#3C948B',
    backgroundColor: '#3C948B',
    height: hp('7%'),
    width: wp('70%'),
    margin: 20,
    alignItems: 'center',
    borderBottomLeftRadius: 10,
    borderTopRightRadius: 10,
  },
  buttonText: {
    flex: 1,
    fontSize: 25,
  },
});

1 个答案:

答案 0 :(得分:0)

您需要为React组件实现一个构造函数。 通常,在React中,构造函数仅用于两个目的:

  • 通过将对象分配给this.state来初始化本地状态
  • 将事件处理程序方法绑定到实例

state = {
 shows: [],
 isLoading: true,
 search: false,
 title: '',
};

替换为

constructor(props){
  super(props);
  this.state = {
    shows: [],
    isLoading: true,
    search: false,
    title: '',
  };
}