【问题标题】:How to read props from a React Native touchable event currentTarget?如何从 React Native 可触摸事件 currentTarget 中读取道具?
【发布时间】:2017-02-08 21:02:59
【问题描述】:

我有以下 React Native 代码,当用户点击图像时运行 press() 方法。我想从事件对象中获取 itemIndex 道具。我在 press 方法中设置了一个断点,并在 Watch 中添加了一些表达式。从手表我确定事件的目标(事件起源)是正确的图像。 itemIndex 道具也可用。正在处理的元素是 currentTarget,Watch 看到它是一个“RCTView”,我期待一个 TouchableOpacity,所以 TouchableOpacity 下面可能是一个 View? currentTarget itemIndex 属性未定义,为什么?如何从 currentTarget 中获取道具?

我想这样做是为了避免为每个渲染项目创建添加方法。

仅供参考, ref={(c) => this._input = c} 将不起作用,因为它正在循环运行。 onPress={(e) => this.press(e, i)} 创建了一个我试图避免的新函数。

观看

  1. target._currentElement.props.itemIndex: 2
  2. target._currentElement.type.displayName: "RCTImageView"
  3. currentTarget._currentElement.props.itemIndex:未定义
  4. currentTarget._currentElement.type.displayName: "RCTView"

    press: function(event){
        var currentTarget = ReactNativeComponentTree.getInstanceFromNode(event.currentTarget);
        var target = ReactNativeComponentTree.getInstanceFromNode(event.target);
        var currentTargetIndex = currentTarget._currentElement.props.itemIndex;
        var targetIndex = target._currentElement.props.itemIndex;
        var url = this.state.data.items[currentTargetIndex].url;
        Linking.openURL(url).catch(err => console.error('An error occurred', err));
    },
    
    render: function() {
    return (
        <ScrollView horizontal={true} showsHorizontalScrollIndicator={false} style={styles.galleryView}>
            {
                this.state.data.items.map((data, i) =>
                    <TouchableOpacity itemIndex={i} key={i} activeOpacity={0.5} onPress={this.press} >
                        <Image itemIndex={i} key={i} source={{uri:data.previewImageUri}} style={styles.galleryImage} />
                    </TouchableOpacity>
                )
            }
        </ScrollView>
    );
    }
    

【问题讨论】:

    标签: react-native


    【解决方案1】:

    我最近实际上遇到了同样的问题,我发现了两种不同的方法可以解决这个问题。更简单的方法是更改​​您的 onPress 以将索引传递给您的新闻功能,这是第二种方法:

    press: function(event, index){
      var url = this.state.data.items[index].url;
      Linking.openURL(url).catch(err => console.error('An error occurred', err));
    },
    
    render: function() {
      return (
        <ScrollView
          horizontal={true}
          showsHorizontalScrollIndicator={false}
          style={styles.galleryView}
        >
        {
          this.state.data.items.map((data, i) =>
            <Images data={data} key={i} index={i} press={this.press} />
          )
        }
        </ScrollView>
        );
    }
    
    const Images = (props) => {
      const imageClicked = (e) => {
        props.press(e, props.index);
      }
      return (
        <TouchableOpacity activeOpacity={0.5} onPress={imageClicked} >
          <Image source={{uri:props.data.previewImageUri}} style={styles.galleryImage} />
        </TouchableOpacity>
      )
    }
    

    【讨论】:

    • AFAIK, onPress={(e) => this.press(e, i)} 创建了一个我试图避免的新函数。我只想将引用传递给我的新闻处理程序并从事件对象中检索索引。
    • 是的,好的,我更新了对第二种方法的回答。基本上,您创建组件并将 index 和 press 函数作为属性传递,并创建一个新函数,该函数将调用您的初始 press 函数,但现在同时传递事件和索引...如果您想让我澄清,请告诉我进一步。
    • 谢谢马特!我得到了它。这个解决方案看起来更像是解决 React Native 错误的方法。我希望有更优雅的东西,或者我只是做错了什么。我会让这个话题挂几天,看看是否有更优雅或“React Native 方式”来执行此操作。如果没有,我将重定向到github.com/facebook/react-native/issues
    • 听起来不错,我也刚刚重新阅读了您的问题,现在我明白了您在寻找什么。这不是错误,您不能只将属性传递给 RN 的组件,而不是它们定义的组件。为了使用文档中未提供的属性,您必须按照我在示例中所做的操作,创建自己的组件来包装它们的组件并传递您自己的属性并通过该过程执行您自己的逻辑。这是 RN 的做法,你只需要将 'Images' 组件移动到它自己的文件中并导入它,代码就会看起来很干净。
    【解决方案2】:

    将所需信息绑定到回调并为每个孩子分配一个,避免在每次渲染孩子时重新创建回调。

    class Hello extends React.Component{
      state = { names: this.props.names.map((name, i) => {
          return Object.assign({
            onClick: this._onClick.bind(this, i, this.props),
          }, name)
        }),
      };
    
      _onClick(ind, _props, e) {
        alert('props:' + JSON.stringify(_props));
      }
    
      render() {
        const { names } = this.state;
        return (
          <div>
            { names.map((name, i) => (
                <div key={i}>Name: <input value={ name.first } onClick={ name.onClick } /></div>
              ))}
          </div>
      )}
    }
    
    ReactDOM.render(
      <Hello names={[{first:'aaa'},{first:'bbb'},{first:'ccc'}]}/>,
      document.getElementById('container')
    );
    

    JS Fiddle

    【讨论】:

      【解决方案3】:

      您可以使您的事件处理程序成为接受额外参数的柯里化函数。

       //Curried function for onPress event handler
        handleOnPress = (someId, someProp) => event => {
          //USE someProp ABOVE TO ACCESS PASSED PROP, WHICH WOULD BE undefined IN THIS CASE
          //Use event parameter above to access event object if you need
          console.log(someProp)
      
          this.setState({
            touchedId: someId
          })
        }
      

      查看下面的工作零食

      https://snack.expo.io/@prashand/accessing-props-from-react-native-touch-event

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多