如何从React Native中的父级调用子方法?

时间:2018-04-19 14:32:54

标签: javascript reactjs react-native

当在我的父组件中触发click事件时,我需要从SearchBar子组件调用closeMenu()方法。我尝试了几种不同的方法,但没有一种方法可行。有谁知道怎么做?

class Products extends Component {

constructor(props) {
    super(props);

    this.state = { closeMenu: false};

    this.hideSearchBar = this.hideSearchBar.bind(this);
}

hideSearchBar(e) {
    console.log('e: ', React.Children)
    this.setState({closeMenu: true});
    this.refs.SearchBar.closeMenu();
    this.setState({closeMenu: false});        
}

componentWillMount() {
    this.props.dispatch(getProductList());
}

render() {
    const {isLoading, products} = this.props.products;

    if (isLoading) {
        return <Loader isVisible={true}/>;
    }

    return (
        <TouchableWithoutFeedback onPress={(e) => this.hideSearchBar(e)} style={{zIndex: 0}}>
            <View style={styles.wrapper}>
                <Header/>
                <View style={styles.bodyWrapper}>
                    <ScrollView style={styles.scrollView}>
                        <ProductsContainer data={{productsList: { results: products }}}/>
                    </ScrollView>
                    <SearchBar ref="SearchBar" style={styles.searchBar} />
                </View>
                <Footer/>
            </View>
        </TouchableWithoutFeedback>
    );
}

}

我也试过调用closeMenu()而没有引用:

hideSearchBar(e) {
    this.setState({closeMenu: true});
    this.SearchBar.closeMenu();
}

这是SearchBar组件:

class SearchBar extends Component {
constructor(props) {
    super(props);
}

componentDidMount() {
    this.suggestions = [];
}

componentWillUpdate(nextProps, nextState) {
    console.log("COMPONENT WILL UPDATE");
    console.log(nextProps);
    console.log(nextState);
}

suggestionClick = (value) => {

}

getSuggestionText = (suggestion) => {

}

onChangeText = (value) => {
    this.selectedSuggestion = false
    this.props.dispatch(handleSearchItemText(value));
    console.log(this.props.products.searchResults);
}

onFocus() {
    const {height} = Dimensions.get('window');
    this.setState({
        contentOffset: {
            x: 0,
            y: height * 1 / 3
        }
    });
}

onBlur() {
    this.setState({
        contentOffset: {x: 0, y: 0}
    });
}

closeMenu = () => {
    this.props.products.searchResults = {};
}

componentWillReceiveProps() {
    if (!this.props.closeMenu) {
        this.props.closeMenu = false;
    }
}

renderSearches = () => {
    this.suggestions = this.props.products.searchResults;
    const suggestionTexts = Object.keys(this.props.products.searchResults || {})

    console.log(suggestionTexts);
    if (!suggestionTexts.length) {
        return null
    }
    // for android absolute element: https://github.com/facebook/react-native/issues/16951
    // https://gist.github.com/tioback/6af21db0685cd3b1de28b84981f31cca#file-input-with-suggestions-L54
    return (
        <View
            ref="suggestionsWrapper"
            style={autoStyles.suggestionsWrapper}
        >
            {
                this.suggestions.map((text, index) => (
                    <TouchableHighlight
                        key={index}
                        suggestionText={text}
                        activeOpacity={0.6}
                        style={autoStyles.suggestion}
                        onPress={this.suggestionClick(this.suggestions[text])}
                        underlayColor='white'
                    >
                        <Text style={autoStyles.suggestionText}>
                            {text}
                        </Text>
                    </TouchableHighlight>
                ))
            }
        </View>
    )
}

render() {
    const myIcon = (<Icon name="search" size={30} style={styles.searchIcon}/>);
    const slidersIcon = (<Icon name="sliders" size={30} style={styles.slidersIcon}/>);

    return (
        <TouchableWithoutFeedback style={{zIndex: 0}}>
            <View style={[styles.searchBar, this.props.style]}>
                <View style={styles.searchContainer}>
                    <View>
                        {slidersIcon}
                    </View>
                    <View style={styles.search}>
                        <View style={styles.searchSection}>
                            {myIcon}
                            <TextInput
                                style={styles.input}
                                placeholder="Search"
                                placeholderTextColor="rgba(0,0,0,0.7)"
                                onChangeText={(searchString) => {
                                    this.setState({searchString})
                                }}
                                underlineColorAndroid="transparent"
                                editable={true}
                                autoCorrect={false}
                                autoFocus={false}
                                autoCaptialize={'none'}
                                autoCorrect={false}
                                onChangeText={this.onChangeText}
                                enablesReturnKeyAutomatically={true}
                                onFocus={() => this.onFocus()}
                                onBlur={() => this.onBlur()}
                            />
                        </View>
                    </View>
                </View>
                {this.renderSearches()}
            </View>
        </TouchableWithoutFeedback>
    );
}

}

1 个答案:

答案 0 :(得分:2)

您应该避免一些问题:

绝不改变道具this.props.something = {}是一种反模式。将道具视为组件不拥有的数据以及不可变的数据。如果他们改变那么只是因为父母传递了新的道具。

此外,您SeachBar中有多个处理程序未绑定this但使用this。不起作用。如果要使用this或将其绑定到constructor

,请使用箭头功能

您应该过度考虑应用的架构。将搜索栏和结果列表拆分为两个独立的组件可能是个好主意。当用户键入内容以搜索更新您的redux存储并将结果显示在一个单独的组件中,只有在有搜索结果时才会呈现。

我担心它会超出stackoverflow答案的长度来解决所有这些问题。也许你应该首先回到基础知识并做一个非常好的redux教程。