【问题标题】:React Native ListView not re-rendering on state change by clickReact Native ListView 不会通过单击重新呈现状态更改
【发布时间】:2016-11-09 18:01:24
【问题描述】:

这是我的示例代码,我希望在点击时更新 ListView 元素。

这一行定义了样式:

(this.state.selectedField.id==field.id)?'green':'white'

在此示例中,活动的View 应以绿色突出显示。 handleClick() 内部的状态正在更新,但没有调用 renderField() 方法。

如何让ListView在点击触发状态改变时重新渲染?

RNPlayNative Link

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

class SampleApp extends Component {

  constructor(props) {
    super(props);
    var ds = new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
    });
    this.state = {
      fields: ds.cloneWithRows([
        {id:0},{id:1},{id:2}
      ]),
      selectedField: {id:0}
    };
  }

  handleClick(field) {
    console.log("Selected field:",field);
    this.setState({
      selectedField: field
    });
  }

  renderField(field) {
    return (
      <TouchableOpacity onPress={this.handleClick.bind(this, field)} >
        <View style={{backgroundColor:(this.state.selectedField.id==field.id)?'green':'white'}}>
          <Text style={{left:0, right:0, paddingVertical:50,borderWidth:1}}>{field.id}</Text>
        </View>
      </TouchableOpacity>
    );
  }

  render() {
    return (
      <View>
        <ListView
          dataSource={this.state.fields}
          renderRow={this.renderField.bind(this)}
        />
      </View>
    );
  }
}

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

【问题讨论】:

标签: listview reactjs onclick react-native react-native-listview


【解决方案1】:

已经回答过很多次了,如果你想改变一个props上的行渲染,如果你想行更新,这个props需要进入你的数据。

查看以下 2 个答案:

【讨论】:

    【解决方案2】:

    这是我对问题的解决方案,但处理每次点击仍然需要很长时间:

    handleClick(field) {
      newFields = this.state.fields.map( (x) => x.key === field.key && x.active !== true ? {...x,active:true} : {...x,active:false})  
      this.setState({
        fields:newFields,
        dataSource: this.state.dataSource.cloneWithRows(newFields)
      });
    }
    

    【讨论】:

      【解决方案3】:

      当数据源更改时,列表会再次呈现,在您的示例中,由于数据源永远不会改变,因此列表视图永远不会重新呈现。这可以通过在状态变量中添加一个字段来保存 dataSource 的数据来实现。在 componentDidMount 方法中,让 dataSource 克隆具有数据状态变量的行。每当您想重新渲染列表视图时,您只需更改数据状态变量,列表将自动重新渲染。我已经更改了您的数据,以便为每个对象添加一个选定状态。这是更新后的代码。

      class SampleApp extends Component {
      
        constructor(props) {
           super(props);
           var ds = new ListView.DataSource({
               rowHasChanged: (row1, row2) => row1 !== row2,
          });
           var dataVar = [
               {
                 id:0,
                 selected: true,
               },{
                 id:1,
                 selected: false,
               },{
                 id:2,
                 selected: false,
               }
             ];
           this.state = {
             data: dataVar,
             fields: ds,
           };
         }
      
         componentDidMount() {
      
           this.setState({
             fields: this.state.fields.cloneWithRows(dataVar)
           });
         }
      
      
         handleClick(field) {
           console.log(field);
           field.selected = !field.selected;
      
           var dataClone = this.state.data;
           console.log(dataClone);
      
           dataClone[field.id] = field;
      
           this.setState({
             data: dataClone,
           });
         }
      
         renderField(field) {
           let color = (field.selected == true)?'green':'white';
           return (
             <TouchableOpacity onPress={this.handleClick.bind(this, field)} >
               <View style={{backgroundColor:color}}>
                 <Text style={{left:0, right:0, paddingVertical:50,borderWidth:1}}>     {field.id}</Text>
               </View>
             </TouchableOpacity>
           );
         }
      
         render() {
           return (
             <View>
               <ListView
                 dataSource={this.state.fields}
                 renderRow={(field) => this.renderField(field)}
               />
             </View>
           );
         }
       }
      

      这是一个有效的 rnplay sample

      【讨论】:

      • 你忘了在componentDidMount中修复这条线:fields: this.state.fields.cloneWithRows(this.state.data)
      • 我尝试了解决方案,但由于某种原因,我无法在更新data 时触发renderField() 功能。 handleClick() 工作正常,data 得到更新。
      • 好的,到目前为止,我已经成功了。我的应用程序有这行:if (!this.state.loaded) { return this.renderLoadingView(); } 用于推迟视图渲染,直到加载数据,由于某种原因阻止了 renderField() 调用。
      猜你喜欢
      • 2019-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-10
      • 2021-10-10
      • 2021-01-12
      • 1970-01-01
      相关资源
      最近更新 更多