Android 创建具有不同回调的TouchableOpacity项网格的最佳方法?

Android 创建具有不同回调的TouchableOpacity项网格的最佳方法?,android,react-native,Android,React Native,我有一个应用程序,我想将图像列表显示为网格,列表上的第一个元素是“添加”按钮。我还需要每个图像都可以触摸。当前我的代码如下所示: class RNtest extends Component { constructor() { super(); this.state = { data: [], counter: 0 //Used to give unique numbers to the items

我有一个应用程序,我想将图像列表显示为网格,列表上的第一个元素是“添加”按钮。我还需要每个图像都可以触摸。当前我的代码如下所示:

class RNtest extends Component {
    constructor() {
        super();

        this.state = {
            data: [],
            counter: 0 //Used to give unique numbers to the items
        };
    }

    itemPicker() {
        var temp = this.state.data;
        temp.push({text: this.state.counter});
        this.setState({
            data: temp,
            counter: this.state.counter + 1
        });
    }

    onPress() {
        console.warn('YO!');
    }

    render()  {
        return (
            <ScrollView style={styles.body}>

                <View style={styles.section}>
                    <Text style={styles.sectionHeader}>ITEMS</Text>

                    <View style={styles.gallery}>
                        <TouchableOpacity
                            style={styles.addButton}
                            onPress={this.itemPicker.bind(this)}
                        >
                            <Text>ADD</Text>
                        </TouchableOpacity>

                        {this.state.data.map(function(item) {
                            return (
                                <TouchableOpacity
                                    style={styles.item}
                                    onPress={this.onPress.bind(this)}
                                >
                                        <Text>{item.text}</Text>
                                </TouchableOpacity>
                            );
                        })}
                    </View>
                </View>

            </ScrollView>
        );
    }

}
显然,onPress函数不起作用,因为显然
这个
在for循环中不可见

我可以使用ListView,但在renderRow中,我必须检查要渲染的项目是否是add按钮,这也会使其他一些部分变得更加困难

在这种情况下我可以使用裁判吗?这是个好主意吗


我正在Android emulator上运行React Native 0.27.2。

尝试使用箭头功能:

{this.state.data.map((item) => {
    // your code
})}
或者您可以使用:

{this.state.data.map(函数(项){
返回(
{item.text}
);
}.bind(this))}

这两种解决方案所做的都是将
this
参数传递到循环内部。

如果您目前遇到的唯一问题是与范围相关的,那么最好通过为处理
this.state.data
map
函数指定一个范围来纠正。然而,我看到了一些其他问题需要对代码进行评论

  • 您的
    itemPicker
    功能通过
    push
    功能直接改变您的状态。选择使用函数,例如
    concat
    ,该函数将返回一个新数组(或扩展运算符)。关于不应该像这样直接改变状态的原因,请参阅

  • 确保将唯一的
    添加到所创建的
    TouchableOpacity
    项目中(请参阅React的警告)

  • 我修改了您的代码示例以演示这些概念:

    import React, { Component } from 'react';
    import {
        ScrollView,
        StyleSheet,
        Text,
        TouchableOpacity,
        View
    } from 'react-native';
    
    class RNTest extends Component {
        constructor(props) {
            super(props);
    
            this.state = {
                data: [],
                counter: 0
            };
        }
    
        itemPicker() {
            // 'push' will mutate, concat will return a new array
            this.setState({
                data: this.state.data.concat({text: this.state.counter}),
                counter: this.state.counter + 1
            });
        }
    
        createButton (item, index) {
            // add a unique key, per react warnings
            return (
                <TouchableOpacity
                    key={index}
                    style={styles.item}
                    onPress={this.onPress}>
                        <Text>{item.text}</Text>
                </TouchableOpacity>
            );
        }
    
        onPress() {
            console.warn('YO!');
        }
    
        render()  {
            return (
                <ScrollView style={styles.body}>
    
                    <View style={styles.section}>
                        <Text style={styles.sectionHeader}>ITEMS</Text>
    
                        <View style={styles.gallery}>
                            <TouchableOpacity
                                style={styles.addButton}
                                onPress={this.itemPicker.bind(this)}
                            >
                                <Text>ADD</Text>
                            </TouchableOpacity>
    
                            {this.state.data.map(this.createButton, this)}
                        </View>
                    </View>
    
                </ScrollView>
            );
        }
    
    }
    
    export default RNTest;
    
    import React,{Component}来自'React';
    进口{
    滚动视图,
    样式表,
    文本,
    可触摸不透明度,
    看法
    }从“反应本机”;
    类RNTest扩展了组件{
    建造师(道具){
    超级(道具);
    此.state={
    数据:[],
    柜台:0
    };
    }
    itemPicker(){
    //“push”将发生变异,concat将返回一个新数组
    这是我的国家({
    data:this.state.data.concat({text:this.state.counter}),
    计数器:this.state.counter+1
    });
    }
    createButton(项目、索引){
    //根据react警告添加唯一密钥
    返回(
    {item.text}
    );
    }
    onPress(){
    控制台。警告('YO!');
    }
    render(){
    返回(
    项目
    添加
    {this.state.data.map(this.createButton,this)}
    );
    }
    }
    输出默认值测试;
    
    谢谢,这台机器运行得很好。我对React Native没有太多经验,所以我很高兴你也指出了我的一些其他错误。
    {this.state.data.map(function(item) {
        return (
            <TouchableOpacity
                style={styles.item}
                onPress={this.onPress.bind(this)}
            >
            <Text>{item.text}</Text>
            </TouchableOpacity>
        );
    }.bind(this))}
    
    import React, { Component } from 'react';
    import {
        ScrollView,
        StyleSheet,
        Text,
        TouchableOpacity,
        View
    } from 'react-native';
    
    class RNTest extends Component {
        constructor(props) {
            super(props);
    
            this.state = {
                data: [],
                counter: 0
            };
        }
    
        itemPicker() {
            // 'push' will mutate, concat will return a new array
            this.setState({
                data: this.state.data.concat({text: this.state.counter}),
                counter: this.state.counter + 1
            });
        }
    
        createButton (item, index) {
            // add a unique key, per react warnings
            return (
                <TouchableOpacity
                    key={index}
                    style={styles.item}
                    onPress={this.onPress}>
                        <Text>{item.text}</Text>
                </TouchableOpacity>
            );
        }
    
        onPress() {
            console.warn('YO!');
        }
    
        render()  {
            return (
                <ScrollView style={styles.body}>
    
                    <View style={styles.section}>
                        <Text style={styles.sectionHeader}>ITEMS</Text>
    
                        <View style={styles.gallery}>
                            <TouchableOpacity
                                style={styles.addButton}
                                onPress={this.itemPicker.bind(this)}
                            >
                                <Text>ADD</Text>
                            </TouchableOpacity>
    
                            {this.state.data.map(this.createButton, this)}
                        </View>
                    </View>
    
                </ScrollView>
            );
        }
    
    }
    
    export default RNTest;