2016-04-24 7 views
0

私はReact Nativeチュートリアルに従っていました。ムービーではなく曲のリストを表示し、Switchコンポーネントを使用してトグル機能を追加しようとしました。子どもの状態に基づいて親のネイティブ条件付きスタイルに反応する

私はこれを動作させることができましたが、スイッチの値を親に送って条件付きスタイルを適用できるようにしようとしています。

私はこれを行うにしようとしたとき、私はtogglePlayedconsole文が呼ばれているように見えることはありませんので、賢明なようだ

undefined is not an object (evaluating 'this.state.played') 

を言って、エラーを取得します。

import React, { 
    AppRegistry, 
    Component, 
    Image, 
    ListView, 
    StyleSheet, 
    Text, 
    View, 
    Switch 
} from 'react-native'; 

var SONGS_DATA = { 
    "songs" : [ 
    { 
     "title" : "I Heard React Was Good", 
     "artist" : "Martin", 
     "played" : false 
    }, 
    { 
     "title" : "Stack Overflow", 
     "artist" : "Martin", 
     "played" : false 
    } 
    ] 
} 

var BasicSwitchExample = React.createClass({ 
    getInitialState() { 
    return { 
     played: false 
    }; 
    }, 
    handlePlayed(value) { 
    console.log('Switch has been toggled, new value is : ' + value) 
    this.setState({played: value}) 
    this.props.callbackParent(value); 
    }, 
    render() { 
    return (
     <View> 
     <Switch 
      onValueChange={this.handlePlayed} 
      style={{marginBottom: 10}} 
      value={this.state.played} /> 
     </View> 
    ); 
    } 
}); 

class AwesomeProject extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     dataSource: new ListView.DataSource({ 
     rowHasChanged: (row1, row2) => row1 !== row2, 
     }), 
     loaded: false, 
    }; 
    } 

    componentDidMount() { 
    this.fetchData(); 
    } 

    getInitialState() { 
    return { 
     played: false 
    }; 
    } 

    togglePlayed(value) { 
    // this is never reached 
    this.setState({played: value}); 
    console.log('Song has been played? ' + this.state.played); 
    } 

    fetchData() { 
    this.setState({ 
     dataSource: this.state.dataSource.cloneWithRows(SONGS_DATA.songs), 
     loaded: true, 
    }); 
    } 

    render() { 
    if (!this.state.loaded) { 
     return this.renderLoadingView(); 
    } 

    return (
     <ListView 
     dataSource={this.state.dataSource} 
     renderRow={this.renderSong} 
     style={styles.listView} 
     /> 
    ); 
    } 

    renderLoadingView() { 
    return (
     <View style={styles.container}> 
     <Text> 
      Loading songs... 
     </Text> 
     </View> 
    ); 
    } 

    renderSong(song) { 
    return (
     // not sure if this syntax is correct 
     <View style={this.state.played ? 'styles.container' : 'styles.played'}> 
     <View style={styles.half}> 
      <Text style={styles.title}>{song.title}</Text> 
      <Text style={styles.artist}>{song.artist}</Text> 
     </View> 
     <View style={styles.half}> 
      <BasicSwitchExample callbackParent={() => this.togglePlayed} /> 
     </View> 
     </View> 
    ); 
    } 
} 

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

AppRegistry.registerComponent('AwesomeProject',() => AwesomeProject); 

React Native Playground

私が反応するように新しいですし、特にネイティブに反応する任意のポインタは素晴らしいことです。

+0

のようになります。P – QoP

+0

ええ、明らかにそれらの曲が上がりません実際のデータではありませんが、私は2つの例をいくつか簡潔にしようとしました。私はそれらを削除することができます、私はちょうどそれらを含める方が良いと思った。 – martincarlin87

+0

あなたの問題は、コンポーネントにtogglePlayedをバインドしていないこと、コンストラクタでバインドするのを忘れてしまったこと、少なくともそれがReactでどのように動作するのか(私はReactネイティブThoについてはわかりません)です。 – QoP

答えて

1

あなたのコンポーネントにあなたの関数をバインドするのを忘れて、それはあなたがそれを読みやすくするために、スタイルや曲を削除する必要があります。この

class BasicSwitchExample extends Component{ 
    constructor(props){ 
     super(props); 
     this.state = { 
     played: false 
     }; 
     this.handlePlayed = this.handlePlayed.bind(this); 
    } 
    handlePlayed(value){ 
     this.setState({played: value}); 
     this.props.callbackParent(value); 
    } 
    render() { 
     return <View> 
     <Switch 
      onValueChange={this.handlePlayed} 
      style={{marginBottom: 10}} 
      value={this.state.played} /> 
     </View> 
    } 
} 
class AwesomeProject extends Component { 
    constructor(props) { 
    super(props); 
    this.renderSong = this.renderSong.bind(this); 
    this.togglePlayed = this.togglePlayed.bind(this); 
    this.fetchData = this.fetchData.bind(this); 
    this.state = { 
     dataSource: new ListView.DataSource({ 
     rowHasChanged: (row1, row2) => row1 !== row2, 
     }), 
     loaded: false, 
    }; 
    } 

    componentDidMount() { 
    this.fetchData(); 
    } 

    togglePlayed(value) { 
    // this is never reached 
    this.setState({played: value}); 
    console.log('Song has been played? ' + this.state.played); 
    } 

    fetchData() { 
    this.setState({ 
     dataSource: this.state.dataSource.cloneWithRows(SONGS_DATA.songs), 
     loaded: true, 
    }); 
    } 

    render() { 
    if (!this.state.loaded) { 
     return this.renderLoadingView(); 
    } 

    return (
     <ListView 
     dataSource={this.state.dataSource} 
     renderRow={this.renderSong} 
     style={styles.listView} 
     /> 
    ); 
    } 

    renderLoadingView() { 
    return (
     <View style={styles.container}> 
     <Text> 
      Loading songs... 
     </Text> 
     </View> 
    ); 
    } 

    renderSong(song) { 
    return (
     // not sure if this syntax is correct 
     <View style={this.state.played ? 'styles.container' : 'styles.played'}> 
     <View style={styles.half}> 
      <Text style={styles.title}>{song.title}</Text> 
      <Text style={styles.artist}>{song.artist}</Text> 
     </View> 
     <View style={styles.half}> 
      <BasicSwitchExample callbackParent={this.togglePlayed} /> 
     </View> 
     </View> 
    ); 
    } 
} 
+0

非常に@ QoPありがとう、(https://rnplay.org/apps/mnanvw)でも同じエラーのようです。条件付きスタイルが削除されても、 'togglePlayed'からのコンソールログにはまだ届かないようですが、アイデアはありますか? – martincarlin87

+0

私が書いたコメントは意味がありませんでした。私はあなたがES5構文を使っているのを見たことがありませんでしたが、とにかく両方ともES6構文で書こうとしています – QoP

+0

うん、これは初めてです。スイッチされた構成要素は、「再生された」が「偽」に初期化された。あなたはあなたの提案で答えを更新できますか?その間に試してみるよ。 – martincarlin87

関連する問題