2015-12-24 4 views
7

Ich baue gerade meine erste reaktionsnative Anwendung, die ein einfacher Klon von IMDB ist. Ich verwende NavigatorIOS, um die Statustransaktion zu verwalten und meine Anwendung so modular wie möglich zu erstellen.Invariant Violation: Elementtyp ist ungültig: erwartet einen String, aber erhalten: Objekt. Überprüfen Sie die Rendermethode von 'NavigatorIOS'

Der Fehler tritt auf, wenn ich zu meinem Film Komponente aus meiner Bibliothek Komponente zu gehen versuchen. Die Bibliothek listet alle Filme auf, die der Benutzer gespeichert hat, und die Movie-Komponente nimmt einfach ein Objekt und zeigt die Informationen des übergebenen Films an.

Die besondere daran ist, dass ich meine Film Komponente von meiner Suche Komponente, und ich bin nicht in der Lage wiederverwenden, die Ausnahme zu reproduzieren.

Bibliothek Komponente:

var React = require('react-native'); 
 
var Separator = require('../Helpers/Separator'); 
 
var Movie = require('../Movie'); 
 

 
var { 
 
    Text, 
 
    StyleSheet, 
 
    View, 
 
    ScrollView, 
 
    TouchableHighlight, 
 
    ActivityIndicatorIOS 
 
} = React; 
 

 
var styles = StyleSheet.create({ 
 
    container: { 
 
    flex: 1, 
 
    }, 
 
    rowContainer: { 
 
    flexDirection: 'column', 
 
    flex: 1, 
 
    padding: 10 
 
    }, 
 
    name: { 
 
    color: '#48BBEC', 
 
    fontSize: 18, 
 
    paddingBottom: 5 
 
    }, 
 
    year: { 
 
    color: '#48BBEC', 
 
    fontSize: 14, 
 
    paddingBottom: 5 
 
    }, 
 
    description: { 
 
    fontSize: 14, 
 
    paddingBottom: 5 
 
    } 
 
}); 
 

 
class Library extends React.Component{ 
 
    selectFilm(selectedMovie){ 
 
    this.props.navigator.push({ 
 
     title: selectedMovie.Title, 
 
     component: Movie, 
 
     passProps: { movie: selectedMovie, canSave: false, isAuthenticated: true } 
 
    }); 
 
    } 
 
    render(){ 
 
    var movies = this.props.movies; 
 
    var list = movies.map((item, index) => { 
 
     return(
 
     <View key={index}> 
 
      <View style={styles.rowContainer}> 
 
      <TouchableHighlight 
 
      onPress={this.selectFilm.bind(this, movies[index])} 
 
      underlayColor='transparent'> 
 
      <Text style={styles.name}>{movies[index].title}</Text> 
 
      </TouchableHighlight> 
 
      <Text stlye={styles.year}>{movies[index].year}</Text> 
 
      </View> 
 
      <Separator /> 
 
     </View> 
 
    ) 
 
    }); 
 
    return(
 
     <ScrollView style={styles.container}> 
 
     {list} 
 
     </ScrollView> 
 
    ) 
 
    } 
 
}; 
 

 
Library.propTypes = { 
 
    movies: React.PropTypes.array.isRequired 
 
}; 
 

 
module.exports = Library;

Film Komponente:

var React = require('react-native'); 
 
var Badge = require('./Badge.js'); 
 
var Library = require('./User/Library.js'); 
 
var Separator = require('./Helpers/Separator'); 
 
var api = require('../Utils/api'); 
 

 
var { 
 
    StyleSheet, 
 
    Image, 
 
    Text, 
 
    View, 
 
    ScrollView, 
 
    TouchableHighlight, 
 
    AsyncStorage 
 
} = React; 
 

 
var styles = StyleSheet.create({ 
 
    container: { 
 
    flex: 1 
 
    }, 
 
    buttonText: { 
 
    fontSize: 18, 
 
    color: 'white', 
 
    alignSelf: 'center' 
 
    }, 
 
    rowContainer: { 
 
    padding: 10 
 
    }, 
 
    rowTitle: { 
 
    color: '#48BBEC', 
 
    fontSize: 16 
 
    }, 
 
    rowContent: { 
 
    fontSize: 19 
 
    }, 
 
    buttonText: { 
 
    fontSize: 18, 
 
    color: '#111', 
 
    alignSelf: 'center' 
 
    }, 
 
    button: { 
 
    height: 45, 
 
    flexDirection: 'row', 
 
    backgroundColor: '#758BF4', 
 
    borderColor: 'white', 
 
    borderWidth: 1, 
 
    borderRadius: 8, 
 
    marginBottom: 0, 
 
    marginTop: 10, 
 
    alignSelf: 'stretch', 
 
    justifyContent: 'center' 
 
    } 
 
}); 
 

 
class Movie extends React.Component{ 
 
    componentDidMount() { 
 
    AsyncStorage.getItem("token").then((value) => { 
 
     this.setState({"token": value}); 
 
    }).done(); 
 
    } 
 
    getRowTitle(title){ 
 
    return title[0] ? title[0].toUpperCase() + title.slice(1): title; 
 
    } 
 
    getTitle(item){ 
 
    return item[0] ? item[0].toUpperCase() + item.slice(1) : item; 
 
    } 
 
    handleSubmit(){ 
 
    api.addMovie(this.state.token, this.props.movie) 
 
     .then((res) => { 
 
      console.log(res); 
 
      if (res === 'Film already exists') { 
 
       alert('Film already exists'); 
 
      } else { 
 
       alert('SAVED'); 
 
      } 
 
     }); 
 
    } 
 
    handleDelete(){ 
 
    api.deleteMovie(this.props.movie.imdbID) 
 
     .then((res) => { 
 
     this.props.navigator.pop(); 
 
     }); 
 
    } 
 
    render(){ 
 
    var showSave; 
 
    if (this.props.isAuthenticated) { 
 
     showSave = (
 
     this.props.canSave ? <TouchableHighlight style={styles.button} onPress={this.handleSubmit.bind(this)} underlayColor="#48BBEC"><Text style={styles.buttonText}> SAVE </Text></TouchableHighlight> : 
 
     <TouchableHighlight style={styles.button} onPress={this.handleDelete.bind(this)} underlayColor="#48BBEC"><Text style={styles.buttonText}>DELETE </Text></TouchableHighlight> 
 
    ); 
 
    } 
 
    var movie = this.props.movie; 
 
    var topicArr = ['director', 'year', 'rated', 'plot', 'country', 'awards', 'imdbRating']; 
 
    var list = topicArr.map((item, index) => { 
 
     if (!movie[item]) { 
 
     item = this.getTitle(item); 
 
     } 
 
     return (
 
     <View key={index}> 
 
      <View style={styles.rowContainer}> 
 
      <Text style={styles.rowTitle}>{this.getRowTitle(item)}</Text> 
 
      <Text style={styles.rowContent}> {movie[item]} </Text> 
 
      </View> 
 
      <Separator /> 
 
     </View> 
 
    ) 
 
    }); 
 
    return(
 
     <ScrollView style={styles.container}> 
 
     <Badge movie={this.props.movie} /> 
 
     {list} 
 
     {showSave} 
 
     </ScrollView> 
 
    ) 
 
    } 
 
}; 
 

 
Movie.propTypes = { 
 
    movie: React.PropTypes.object.isRequired 
 
}; 
 

 
module.exports = Movie;

Suchen Komponente:

var React = require('react-native'); 
 
var Movie = require('./Movie'); 
 
var api = require('../Utils/api'); 
 

 
var { 
 
    Text, 
 
    View, 
 
    TextInput, 
 
    TouchableHighlight, 
 
    StyleSheet, 
 
    ActivityIndicatorIOS, 
 
    AsyncStorage 
 
} = React; 
 

 
var styles = StyleSheet.create({ 
 
    // Styles 
 
}); 
 

 
class Search extends React.Component{ 
 
    constructor(props){ 
 
    super(props); 
 
    this.state = { 
 
     title: '', 
 
     isLoading: false, 
 
     token: '' 
 
    } 
 
    } 
 
    componentDidMount() { 
 
    AsyncStorage.getItem("token").then((value) => { 
 
     this.setState({"token": value}); 
 
    }).done(); 
 
    } 
 
    handleChange(event){ 
 
    this.setState({ 
 
     title: event.nativeEvent.text 
 
    }); 
 
    } 
 
    handleSubmit(){ 
 
    var isAuthenticated = this.state.token !== null ? true : false; 
 
    this.setState({ 
 
     isLoading: true 
 
    }); 
 
    api.findMovie(this.state.title) 
 
     .then((res) => { 
 
     if (!res.Response) { 
 
      this.setState({ 
 
      error: 'Movie not found', 
 
      isLoading: false 
 
      }); 
 
     } else { 
 
      this.props.navigator.push({ 
 
       title: res.Title, 
 
       component: Movie, 
 
       passProps: {movie: res, canSave: true, isAuthenticated: isAuthenticated} 
 
      }); 
 
      this.setState({ 
 
      isLoading: false, 
 
      error: false, 
 
      title: '' 
 
      }) 
 
     } 
 
     }); 
 
    } 
 
    render(){ 
 
    var showErr = (
 
     this.state.error ? <Text>{this.state.error}</Text> : <View></View> 
 
    ); 
 
    return(
 
     <View style={styles.mainContainer}> 
 
     <Text style={styles.title}>Search for a movie</Text> 
 
     <TextInput 
 
      style={styles.searchInput} 
 
      value={this.state.title} 
 
      onChange={this.handleChange.bind(this)} /> 
 
     <TouchableHighlight 
 
      style={styles.button} 
 
      onPress={this.handleSubmit.bind(this)} 
 
      underlayColor="white"> 
 
      <Text style={styles.buttonText}> SEARCH </Text> 
 
     </TouchableHighlight> 
 
     <ActivityIndicatorIOS 
 
      animating={this.state.isLoading} 
 
      color= "#111" 
 
      size="large"> 
 
     </ActivityIndicatorIOS> 
 
     {showErr} 
 
     </View> 
 
    ) 
 
    } 
 
}; 
 

 
module.exports = Search;

Hier ist die Anwendung Fluss meiner App:

Application Flow Jede Hilfe wäre sehr geschätzt.

+0

da es keinen Fehler gibt, wenn aus der Suche kommt, ich denke, es wäre hilfreich, diese Komponente zu sehen. Im Allgemeinen schlage ich vor, die dynamischen Bits durch hartcodierte Bits zu ersetzen, um das Problem zu isolieren. Eine der Requisiten, die an NavigatotIOS übergeben werden, ist eigentlich ein Objekt statt String –

+0

Danke, ich habe den Code für die Search-Komponente hinzugefügt. Ich habe alle Requisiten fest programmiert und es gibt mir immer noch den gleichen Fehler. – gonzalovazzquez

Antwort

2

Schließlich finden Sie es heraus!

Dummer Fehler von meiner Seite.

Die Lösung war die Voraussetzung für die Bibliothek Komponente aus dem Film Komponente zu entfernen. Sobald ich diese Zeile gelöscht habe, war der Fehler verschwunden. Es scheint, dass Sie nicht die gleiche Komponente benötigen, von der Sie übergehen, wenn Sie Ihren Code beschädigen.

+12

so ... es scheint, Sie hatten ein schönes Weihnachten: D –

1

Ich habe diesen Fehler erhalten, weil ich die Komponente zweimal registriert habe.

Verwandte Themen