React Native List View Not Changing Style on State Change

时间:2016-04-25 08:46:43

标签: reactjs react-native

My aim is to toggle a switch component and for that change in value to affect the state of the parent which will be rendered with a different style than from the default rendered style.

At the moment the state updates fine but the component isn't re-rendered.

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
    }
  ]
}

class BasicSwitchExample extends Component{
    constructor(props){
      super(props);
      this.state = {
         played: false
       };
       this.handlePlayed = this.handlePlayed.bind(this);
    }
    handlePlayed(value){
        console.log('handlePlayed value: ' + value);
        this.setState({played: value});
        this.props.callbackParent(value);
    }
    render() { 
      return <View> // this has to be on the same line or it causes an error for some reason
        <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) {
    let bgStyle = this.state.played ? styles.played : styles.container;
    console.log('style : ' + bgStyle); // prints 2 for some reason
    return (
      <View style={this.state.played ? styles.played : styles.container}>
        <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({
  container: {
    /* styles here */
  },
  played: {
    /* styles here */
  },

});

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

React Native Playground

For some reason when rendering the style, it's printed out as 2. This only happens when the app is first loaded and is never reached after a switch is toggled.

1 个答案:

答案 0 :(得分:2)

您不会改变任何与ListView呈现相关的状态。在togglePlayed中,您必须更改将更改呈现列表的状态部分:https://rnplay.org/apps/z0fKKA