【问题标题】:React-Native ListView renderRow issues passing props. The right way or the wrong wayReact-Native ListView renderRow 问题传递道具。正确的方式或错误的方式
【发布时间】:2016-06-25 02:29:59
【问题描述】:

在 React-Native 中使用 ListView,我看到不一样,将 props 移动到列表项,

  1. 仅通过引用将函数作为道具传递,并在子组件中调用参数,或者

  2. 将函数作为定义了参数的 props 传递,并在子节点中调用不带参数的函数

所有解决方案均无效。

调用的函数是 Redux 的 Actions 创建者,并被分派。这是 Redux 还是 React-Native 的问题(可能是 ReactJS)

这是一个sn-p,市场为//错误的代码行不起作用,然后是好的代码行

class App extends Component {

  // On props 
  // data: an Array
  // doThis: an action creator of Redux
  // doThat: idem

  constructor(){
    super();
    this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
  }

  render () {
    const dataSource = this.ds.cloneWithRows(this.props.data);

    return (
      <View>
        <ListView style={{flex:1}}
            dataSource={dataSource}
            renderRow={(rowData, sectionID, rowID) =>
              <Item  rowData={rowData}
              //ERROR
              //onPress={this.props.doThis}
              //onLongPress={this..props.doThat}
              //RIGHT NO ERROR TOO
              onPress={() => this.props.doThis(rowData)}
              onLongPress={() => this.props.doThat(rowData)}
              />
            }
          />
      </View>
    )
  }
}

class Item extends Component {
  render() {
    return (
      <View>
        <TouchableHighlight
          //ERROR 
          //onPress={() => { this.props.onPress( this.props.rowData ) }}
          //onLongPress={() => { this.props.onLongPress( this.props.rowData ) }}
          //WRONG TOO
          onPress={this.props.onPress}
          onLongPress={this.props.onLongPress}
          >
          <Text>
            {rowData}
          </Text>
        </TouchableHighlight>
      </View>
    );
  }
}

这里有一个关于这个问题的回购https://github.com/srlopez/test 提前致谢

【问题讨论】:

    标签: android ios reactjs react-native redux


    【解决方案1】:

    如果您的高级回调接受一个参数,您需要确保您的匿名函数也接受一个参数(注意:使用箭头语法创建匿名函数会自动将我们的函数绑定到当前的 this 的值语境)。我认为您目睹了您的回调绑定到不正确的上下文(窗口)或您不接受传递的参数的问题的组合:

    class App extends Component {
    
      // On props 
      // data: an Array
      // doThis: an action creator of Redux
      // doThat: idem
    
      constructor(){
        super();
        this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
      }
    
      render () {
        const dataSource = this.ds.cloneWithRows(this.props.data);
    
        return (
          <View>
            <ListView style={{flex:1}}
                dataSource={dataSource}
                renderRow={(rowData, sectionID, rowID) => 
                  <Item rowData={rowData}
                      onPress={(data) => this.props.doThis(data)}
                      onLongPress={(data) => this.props.doThat(data)} />
                }/>
          </View>
        )
      }
    }
    
    class Item extends Component {
      render() {
        return (
          <View>
            <TouchableHighlight
              onPress={() => this.props.onPress(this.rowData)}
              onLongPress={() => this.props.onLongPress(this.rowData)}>
              <Text>
                {rowData}
              </Text>
            </TouchableHighlight>
          </View>
        );
      }
    }
    

    【讨论】:

    • 感谢@calvin-belden,我在repo 上尝试了您的方法,但结果行为是相同的。我在 ListView 的 renderRow 上编写了 'onPress={(rowID) => {this.props.update(rowID)}}`,在 Item 上编写了 onPress={()=&gt;this.props.onPress(rowID)},并且 Item 发生了变化,但剩余的项目被删除了。
    • 是否在Item组件的render函数中定义了rowID?你能设置一个断点(或以某种方式调试)来查看是否调用了父处理程序吗?
    • 你好@calvin-belden @moti-azu。完毕!正确的方法是这样的 onPress={() =&gt; this.props.update(parseInt(rowID))} 在 renderRow 上,onPress={this.props.onPress} 在 Item 上。但重要的是回购中的rowIDparseInt。 rowID 是字符串而不是数字!然后reducer(Redux)中的函数总是转换为0,然后就全错了!非常感谢!
    • 我很好奇除了箭头符号之外还有其他方法吗?那么,除了onPress={(data) =&gt; this.props.doThis(data),还有什么相当于onPress={this.props.doThis.bind(this, data)?或者类似的东西?
    • 您不会绑定 data 参数,因为这在绑定时是未知的;触发事件时,data 将传递给您的事件侦听器。但除此之外[功能上]没有区别。使用 Function.prototype.bind 会影响性能,而且我还发现箭头语法更简洁。
    【解决方案2】:

    这可能是您的 this 未正确设置在您的闭包中的问题。

    尝试这样绑定:

    class Item extends Component {
      render() {
        return (
          <View>
            <TouchableHighlight
              onPress={this.props.onPress.bind(this, this.props.rowData)}
              onLongPress={this.props.onLongPress.bind(this, this.props.rowData)}
              >
              <Text>
                {rowData}
              </Text>
            </TouchableHighlight>
          </View>
        );
      }
    }
    

    【讨论】:

    • 嗨@Moti Azu,我真的不知道我的回答和你的回答有什么问题。都错了。我正在考虑在 renderRow 和 Item 上传递 callbak 的正确方法只是调用该函数。但不起作用。这是要测试的仓库,我可以帮助我:https://github.com/srlopez/test
    • 嗨@Moti Azu 为了避免在这里进行扩展讨论(不喜欢评论者),我删除了我的 cmets。详细的解释在 repo 上。单击主组件上的按钮可以正常工作(在列表中添加、删除、更新等),但单击列表上的项目,不会产生相同的行为,然后从单击的项目中删除所有项目到最后。所需的行为是更改项目的状态,但状态会更改并删除剩余的项目。对不起莫蒂我糟糕的英语。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 2018-05-22
    • 2016-11-10
    • 1970-01-01
    • 2019-10-07
    相关资源
    最近更新 更多