2015-04-16 2 views
3

В следующем коде, когда setState вызывается из campaignsUpdated, render получает вход в консоль, но не renderRow:Реагировать Native: 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 

Что я здесь делаю неправильно?

ответ

0

Вы передаете ListView функцию renderRow, которая возвращает компонент. Вы должны были бы вызвать эту функцию в пределах ListView после ее передачи, предположительно во время карты над campaigns.

+0

Кроме того, кажется, что вы звоните 'this.renderRow.bind (это)', но я не вижу причин для прохождения контекст для 'renderRow'. –

+0

Почему мне нужно вызывать renderRow? Он корректно отображается в первый раз, поэтому я предполагаю, что списки ListView отображаются в кампаниях, как вы упомянули, без того, что компонент должен это сделать. – tldr

+0

Упущено, что это было связано с родным извините. Не нужно бить функцию 'rowHasChanged', потому что либо ваши данные не изменяются, либо' cloneWithRows' не вызывает rowChange? –

0

По его мнению, наиболее вероятный случай заключается в том, что у вас есть классическая проблема изменчивости Реата.

I.e. Я подозреваю, что ваш метод «campaignUpdated» вызывается с тем же экземпляром массива, который был получен в последний раз, или элементы в списке - это те же экземпляры.

Попробуйте использовать:

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

Если это не сработает, то вы либо сделать ту часть, которая управляет ваш список compaigns создавать новые копии при внесении изменений (например, const clone = {...campaign, title:"A new Title"}) или обновить rowHasChanged метод, чтобы увидеть, действительно ли название (или любые необходимые вам данные) изменилось.

Вот два очень хороших видео о неизменности в JavaScript здесь: 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

Смежные вопросы