React Native: renderRow fails

The following code, when setState

called from campaignsUpdated

, is render

logged to the console, but not renderRow

:

var React = require('react-native'),

Bus = require('../Bus'),
styles = require('../Styles'),
CampaignsStore = require('../stores/Campaigns'),
CampaignItem = require('./CampaignItem'),

{
  Component,
  Text,
  TextInput,
  ListView,
  View,
  NavigatorIOS,
  ActivityIndicatorIOS
} = React


class CampaignList extends Component {
    constructor(props) {
      super(props)

      this.state = {
        dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})
      }
    }

    componentDidMount() {
      this.addListeners()
      Bus.emit('campaigns:search', '')
    }

    componentWillUnmount() {
      this.removeListeners()
    }

    render() {
      console.log('render')
      return (
        <View style={styles.container}>
          <TextInput
            style={styles.searchInput}
            placeholder='Campaign Name'
            value={this.state.campaignName}
            onChange={this.campaignSearchChanged.bind(this)}/>
          <ListView
            dataSource = {this.state.dataSource}
            renderRow = {this.renderRow.bind(this)}/>
        </View>
      )
    }

    renderRow(campaign) {
      console.log('renderRow')
      return <CampaignItem campaign={campaign}/>
    }

    addListeners() {
      Bus.on({
        'campaigns:updated': this.campaignsUpdated.bind(this)
      })
    }

    removeListeners() {
      Bus.off({
        'campaigns:updated': this.campaignsUpdated.bind(this)
      })
    }

    campaignsUpdated(event) {
      var campaigns = event.data
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(campaigns)
      })
    }

    campaignSearchChanged(event) {
      var campaignName = event.nativeEvent.text
      Bus.emit('campaigns:search', campaignName)
    }
}

module.exports = CampaignList

      

What am I doing wrong here?

+3


source to share


2 answers


You are passing a ListView

function renderRow

that returns a component. You would have to call this function within ListView

after passing it, presumably during the map over campaigns

.



0


source


In his opinion, the most likely case is that you have the classic reactivity variation problem here.

those. I suspect that your "campaignUpdated" method is being called with the same instance of the array it last received, or the items in the list are the same instances.

Try using:



campaignsUpdated(event) { var campaigns = event.data.slice(); // <-- clone the array this.setState({ dataSource: this.state.dataSource.cloneWithRows(campaigns) }) }

If that doesn't work, then you either make the part that manages your campaign list, create new copies when you make changes (for example const clone = {...campaign, title:"A new Title"}

), or update your rowHasChanged method to see if there is a header (or whatever data you need) actually has changed.

Here are two really good videos on immutability in JavaScript here: https://egghead.io/lessons/javascript-redux-avoiding-array-mutations-with-concat-slice-and-spread https://egghead.io/lessons/ javascript-redux-avoiding-object-mutations-with-object-assign-and-spread

0


source







All Articles