React Component Props迟到了。 (流星JS)

时间:2018-11-22 11:32:05

标签: reactjs react-native meteor react-redux

我正在做一个本机和流星js项目。 我的问题是,从withTracker()函数接收的道具仅在 componentDidUpdate(prevProps)中接收,而在构造函数或componentWillMount中却没有。 另一个问题是当我将道具直接从父母传递给孩子时。它迟到了,因为我的组件没有更新 iconGroups 道具来自withTracker()方法 和我在此 showGroupIcons()中使用的 openSection 道具 直接从父级传递到此组件。 我想打开通过父母传递给它的Accordian部分。但是问题出在 componentDidUpdate(prevProps)中,由于要重新渲染哪个组件,我正在更改状态。 openSection变量的默认值为零。当道具敬畏时,它会更改我需要的值,但Accordian不会更新。

下面是我的代码

import React, { Component } from 'react';
import Meteor, { withTracker } from 'react-native-meteor';
import {
    View, Image, ScrollView, TouchableOpacity,
} from 'react-native';
import PopupDialog from 'react-native-popup-dialog';
import {Text, Icon, Input, Item, List,} from 'native-base';
import Accordion from 'react-native-collapsible/Accordion';
import { Col, Row, Grid } from 'react-native-easy-grid';
import styles from './styles';
import CONFIG from '../../config/constant';

import {MO} from "../../index";

const staticUrl = '../../assets/img/icons/';

class IconPickerComponent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            dataSource: [],
            itemName: 'apple1',
            activeSections: 0,
            showAccordian: true,
            accordianData: []
        };
    }

    componentDidUpdate(prevProps) {
        if(prevProps.iconGroups !== this.props.iconGroups) {
            let images = this.props.iconGroups.map(icon => icon.images);
            let flatten = [].concat.apply([], images).map(img => { return {name: img, icon: CONFIG.ICON_URL+img+'.png'} })
            this.setState({ filteredItems: flatten, dataSource: flatten, accordianData: this.props.iconGroups });
        }
    }

    componentDidMount() {
        this.props.onRef(this);
    }

    componentWillUnmount() {
        this.props.onRef(null);
    }

    method() {
        // this.setState(...this.state,{
        //     searchText: ''
        // })
        this.iconPicker.show(); // show icon picker
    }

    onSearchChange(text) {
        this.setState({
            showAccordian: !(text.length > 0)
        });
        const searchText = text.toLowerCase();
        const filteredItems = this.state.dataSource.filter((item) => {
            const itemText = item.name.toLowerCase();
            return itemText.indexOf(searchText) !== -1;
        });
        this.setState({ filteredItems });

    }

    onIconSelect(item) {
        this.setState({
            itemName: item,
        });
        this.iconPicker.dismiss();
        if (this.props.onIconChanged) {
            this.props.onIconChanged(item);
        }
    }
    _renderSectionTitle = section => {
        return (
            <View style={styles.content}>
                <Text></Text>
            </View>
        );
    };

    _renderHeader = section => {
        return (
            <View style={styles.accordHeader}>
                <Text style={{color: 'white'}}>{this.state.showAccordian} - {section.group}</Text>
                <Text>
                    <Icon style={styles.downArrow} name="ios-arrow-down" />
                </Text>
            </View>
        );
    };

    _renderContent = section => {
        return (
            <View style={styles.accordContent}>
                {
                    section.images.map((img, key) => (
                        <TouchableOpacity onPress={() => this.onIconSelect(img)} key={key}>
                            <View style={styles.iconsGrid}>
                                <Image style={styles.image} source={{uri: CONFIG.ICON_URL+ img + '.png'}}/>
                            </View>
                        </TouchableOpacity>
                    ))
                }
            </View>
        );
    };

    _updateSections = activeSections => {
        this.setState({ activeSections });
    };

    hasGroupIcons() {
        return this.props.iconGroups.length > 0;
    };

    showGroupIcons() {
        if(this.state.showAccordian){
            let openSection;
            if(!!this.props.openSection) {
                let groupIndex = this.state.accordianData.findIndex(icon => icon.group === this.props.openSection);
                if(groupIndex !== -1) {
                    openSection = groupIndex;
                } else {
                    openSection = 0;
                }
            } else {
                openSection = 0;
            }
            return(<Accordion
                sections={this.state.accordianData}
                activeSections={this.state.activeSections}
                renderSectionTitle={this._renderSectionTitle}
                renderHeader={this._renderHeader}
                renderContent={this._renderContent}
                onChange={this._updateSections}
                initiallyActiveSection={openSection} />);
        } else {
            return(<View style={{flexWrap: 'wrap', flexDirection: 'row'}}>
                {
                    this.state.filteredItems.map((item, key) => (
                        <TouchableOpacity onPress={() => this.onIconSelect(item.name)} key={key}>
                            <View style={styles.iconsGrid}>
                                <Image style={styles.image} source={{uri: item.icon}}/>
                            </View>
                        </TouchableOpacity>
                    ))
                }
            </View>)
        }
    };

    render() {
        return (
            <PopupDialog
                overlayOpacity={0.8}
                overlayBackgroundColor="#414141"
                dialogStyle={styles.dialogBox}
                containerStyle={styles.dialogContainer}
                ref={(popupDialog) => { this.iconPicker = popupDialog; }}
            >
                <ScrollView>
                    <View style={styles.dialogInner}>
                        <Item searchBar rounded style={styles.searchbar}>
                            <Icon style={styles.searchIcon} name="search" />
                            <Input onChangeText={this.onSearchChange.bind(this)} style={styles.inputSearch} placeholder="Search" />
                        </Item>
                        {
                            this.hasGroupIcons() && this.showGroupIcons()
                        }
                    </View>
                </ScrollView>
            </PopupDialog>
        );
    }
}

export default withTracker(params => {
    MO.subscribe('ipSubsId3', 'IconGroups');
    return {
        iconGroups: MO.collection('IconGroups', 'ipSubsId3').find({}),
    };
})(IconPickerComponent);

我是新来的反应者。我假设道具更改组件时会重新渲染。

2 个答案:

答案 0 :(得分:1)

使用这种生命周期方法

static getDerivedStateFromProps(prevProps, prevState) {
        if(prevProps.iconGroups !== this.props.iconGroups) {
            let images = this.props.iconGroups.map(icon => icon.images);
            let flatten = [].concat.apply([], images).map(img => { return {name: img, icon: CONFIG.ICON_URL+img+'.png'} })
            this.setState({ filteredItems: flatten, dataSource: flatten, accordianData: this.props.iconGroups });
        }
    }
  

getDerivedStateFromProps在初始安装和后续更新上都在调用render方法之前被调用。它应该返回一个对象以更新状态,或者返回null则不更新任何内容。

Read more about this lifecycle method here

答案 1 :(得分:0)

我已解决此问题。其实我的概念是不对的。我认为道具是首先在构造函数和componentWillMount中获得的。但是我在render()中获得了所有道具,并且一切正常,我现在不必使用任何生命周期方法来使用道具