React Component Реквизит получают поздно.(Метеор JS) - PullRequest
0 голосов
/ 22 ноября 2018

Я работаю над реактивным и метеорным проектом js.Моя проблема в том, что реквизиты, полученные из функции withTracker (), принимаются только в componentDidUpdate (prevProps) Я не получаю их в конструкторе или componentWillMount.Другая проблема, когда я передаю реквизит непосредственно от родителя ребенку.он получает их поздно, из-за чего мой компонент не обновляет iconGroups prop происходит из метода withTracker () и openSection реквизитов, которые я использую в этом showGroupIcons () передается напрямую от родителя к этому компоненту.Я хочу открыть раздел 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 голосов
/ 24 ноября 2018

Я исправил эту проблему.На самом деле мои концепции не были правильными.Я думал, что реквизиты впервые получены в конструкторе и componentWillMount.Но я получаю все реквизиты в render (), и все работает нормально, мне не нужно использовать какой-либо метод жизненного цикла, чтобы использовать реквизит сейчас

0 голосов
/ 22 ноября 2018

Используйте этот метод жизненного цикла

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 вызывается непосредственно перед вызовом метода рендеринга как при первоначальном монтировании, так и при последующих обновлениях.Он должен возвращать объект для обновления состояния или ноль для обновления ничего.

Подробнее об этом методе жизненного цикла можно прочитать здесь

...