简体   繁体   English

如何在 React Native 的类组件中将函数作为道具传递和执行?

[英]How to pass and execute functions as props in class Component in React Native?

I'm a beginner in React Native and struggling in passing and executing functions as props from parent to child component.我是 React Native 的初学者,正在努力将函数作为道具从父组件传递到子组件并执行。 Here's the code:这是代码:

MainMap主地图

import React from 'react';
import { 
    TouchableWithoutFeedback,
    StyleSheet,
    View,
    Button,
    FlatList,
    Dimensions
} from 'react-native';

import PlaceInput from '../components/PlaceInput';

const INCREMENT = 1;
const HEIGHT = Dimensions.get('window').height
const WIDTH = Dimensions.get('window').width

class MainMap extends React.Component{
    constructor(props){
        super(props);
        this.state={
            numOfInput:[],
            counter: 0,
        }
        this.onAddSearch = this.onAddSearch.bind(this)
        this.onDeleteSearch = this.onDeleteSearch.bind(this)
    }

    onAddSearch(){
        this.setState((state) => ({
            counter: state.counter + INCREMENT,
            numOfInput: [...state.numOfInput, state.counter]
        }))
    }

    onDeleteSearch(inputId){
        const items = this.state.numOfInput.filter(item => item.id !== inputId)
        this.setState({
            numOfInput: items
        })
    }
    render(){
            return(
                <TouchableWithoutFeedback onPress={this.hideKeyboard} >
                    <View style={styles.container} >

                        <Button title='Add a location' onPress={this.onAddSearch} />
                        <View style={{height: HEIGHT/2 }}>
                            <FlatList
                                data={this.state.numOfInput}
                                keyExtractor={(item, index) => item.id}
                                renderItem={itemData => {
                                    return(
                                        <PlaceInput
                                            key={itemData.item.id}
                                            // id={itemData.item.id}
                                            onDelete={this.onDeleteSearch}
                                            showDirectionOnMap={this.showDirectionOnMap}
                                            userLatitude={userLatitude}
                                            userLongitude={userLongitude}
                                        />
                                    )
                                }}
                            />
                        </View>
                    </View>
                </TouchableWithoutFeedback>
            )
        }
    }

export default MainMap;

const styles = StyleSheet.create({
    container:{
        flex: 1
    },
})

Here's the PlaceInput component这是 PlaceInput 组件

class PlaceInput extends React.Component{
    constructor(props){
        super(props);
        ... // These lines have no relation to what I'm asking so don't mind them
  }
    ...
    render(){
        return(
            <View style={styles.buttonContainer} >
                    <View style={{flex: 1, alignItems: 'center'}}>
                        <Text style={{fontSize: 8}}>{'\u25A0'}</Text>
                    </View>
                    <View style={{flex: 4}}>
                        <TextInput 
                            autoCorrect={false}
                            autoCapitalize='none'
                            style={styles.inputStyle}
                            placeholder='Search your places'
                            onChangeText={(input) => {
                                this.setState({destinationInput: input});
                                this.getPlacesDebounced(input);
                            }}
                            value={this.state.destinationInput}
                        />
                        {/* {predictions} */}
                    </View>
                    <View style={styles.rightCol}>
                        <TouchableOpacity onPress={this.props.onDelete.bind(this, this.props.id)}>
                            <Ionicons name='md-car' size={25} style={{alignSelf: 'center'}} />
                        </TouchableOpacity>
                    </View>
                </View>
        )
  }
}

What I'm trying to do:我正在尝试做的事情:

  • Define a function to execute in MainMap.js (in FlatList --> PlaceInput for specific) , which is to delete an search bar( the whole PlaceInput in the FlatList) every time I click the right symbol of that search bar.定义一个在 MainMap.js 中执行的函数(在 FlatList --> PlaceInput for specific),即每次单击该搜索栏的右侧符号时删除一个搜索栏(FlatList 中的整个 PlaceInput)。 The function is onDeleteSearch函数是onDeleteSearch

  • The right symbol is styled in a TouachableOpacity as you can see in the PlaceInput.js component.正如您在 PlaceInput.js 组件中看到的那样,正确的符号在 TouachableOpacity 中设置了样式。 I put it in the last View pair我把它放在最后一个视图对中

  • However, When I click, the screen deletes all the search bars, not the one I click.但是,当我单击时,屏幕会删除所有搜索栏,而不是我单击的搜索栏。 Is it the problem of the id of the component PlaceInput ?是组件 PlaceInput 的 id 的问题吗? Or with the way I call the props?...还是用我调用道具的方式?...

Please help me !请帮我 !

<TouchableOpacity onPress={this.props.onDelete.bind(this, this.props.id)}>
     <Ionicons name='md-car' size={25} style={{alignSelf: 'center'}} />
</TouchableOpacity>

Don't bind, just call this.props.onDelete(this.props.id);不绑定,直接调用this.props.onDelete(this.props.id);

In MainMap , try this:MainMap ,试试这个:

<PlaceInput
  key={itemData.item.id}
  // id={itemData.item.id}
  onDelete={() => this.onDeleteSearch(itemData.item.id)} // here
  showDirectionOnMap={this.showDirectionOnMap}
  userLatitude={userLatitude}
  userLongitude={userLongitude}
/>

Assuming the function:假设函数:

onPressed(optionalArgument = false) {
   // do something
}

You can pass a function to onPress if it does not require any arguments, ie如果不需要任何参数,您可以将函数传递给 onPress,即

onPress={onPressed} // - would work if no arguments required.
onPress={onPressed(argument)} // - will get fired on component render
onPress={()=> onPressed(argument)} // - will work as expected on button press
onPress={()=> { // - will work as expected on button press
    // Multiple lines of code
    onPressed(argument);
    anotherFunction();
    }
};

In your MainMap you are doing everything correctly, just uncomment the在您的 MainMap 中,您所做的一切都正确,只需取消注释

// id={itemdata.item.id}

In PlaceInput, just one small change:在 PlaceInput 中,只有一个小改动:

<TouchableOpacity onPress={() => this.props.onDelete(this.props.id)}>
   <Ionicons name='md-car' size={25} style={{alignSelf: 'center'}} />
</TouchableOpacity>

If you don't add ()=> to your onPress, the function gets called immediately, that's why you see such behaviour.如果您不将 ()=> 添加到您的 onPress,该函数会立即被调用,这就是您看到此类行为的原因。

Your numOfInput is just a list of numbers, so instead of using item.id -s use item directly.你的numOfInput只是一个数字列表,所以不要使用item.id -s 直接使用item

Here:这里:

const items = this.state.numOfInput.filter(item => item !== inputId)

And here和这里

<PlaceInput
  key={itemData.item}
  // id={itemData.item}
  ...
/>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM