Реагируйте на избыточность: данные об изменении состояния странно изменяются при обновлении компонента - PullRequest
0 голосов
/ 14 мая 2019

Я новичок, чтобы реагировать на родных. Я столкнулся с какой-то странной проблемой с 3 дней. У меня есть компонент, который имеет подкомпоненты (3 подкомпонента). Я переключаюсь между подкомпонентами с помощью элемента ButtonGroup из response-native-elements

когда я выбираю данные из API, первый раз, когда мой подкомпонент 1 загружается нормально с ожидаемыми данными, но когда я переключаюсь на подкомпонент 2 (или подкомпонент 3) и снова возвращаюсь к подкомпоненту 1, родительский компонент, который подключен к хранилищу, обновляется различными значениями данных, которые передаются каждому подкомпоненту. Я не знаю почему. Может быть, я что-то упустил или я делал глупости с 3-х дней.

Вот мой код.

  • Родительский компонент: PurchaseMonth
import React, { Component, Fragment } from 'react';
import { StyleSheet, ScrollView, View } from 'react-native';
import MainView from '../../../core/layout/MainView';
import { ButtonGroup, Text, Icon } from 'react-native-elements';
import PurchaseMonthTable from './PurchaseMonthTable';
import PurchaseMonthChart from './PurchaseMonthChart';
import PurchaseMonthDetails from './PurchaseMonthDetails';
import MainHeader from '../../../core/layout/MainHeader';
import { getMonthPurchases } from '../actions/actions';
import Spinner from '../../../core/layout/Spinner';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

const tableHead = ['JOUR', 'B1', 'B2', 'B3', 'B4'];

class PurchaseMonth extends Component {

    constructor(props) {
        super(props);

        this.state = {
            selectedIndex: 0
        };
    }

    componentDidMount() {
        const { getMonthPurchases, profile } = this.props;

        getMonthPurchases(profile.numero, profile.password);
    }

    _updateIndex = (selectedIndex) => {
        this.setState({selectedIndex});
    }

    tableLabel = () => {
        const { selectedIndex } = this.state;
        const color = selectedIndex === 0 ? 'white' : '#00151C';

        return (
            <View>
                <Icon type="font-awesome" name="table" iconStyle={{color: color}} />
                <Text style={{color: color}}>Tableau</Text>
            </View>
        );
    }

    chartLabel = () => {
        const { selectedIndex } = this.state;
        const color = selectedIndex === 1 ? 'white' : '#00151C';

        return (
            <View>
                <Icon type="font-awesome" name="line-chart" iconStyle={{color: color}} />
                <Text style={{color: color}}>Graphe</Text>
            </View>
        );
    }

    detailsLabel = () => {
        const { selectedIndex } = this.state;
        const color = selectedIndex === 2 ? 'white' : '#00151C';

        return (
            <View>
                <Icon type="font-awesome" name="info-circle" iconStyle={{color: color}} />
                <Text style={{color: color}}>
                Détails par produit
                </Text>
            </View>
        );
    }

    render() {
        const { navigation, purchases, isLoading } = this.props;
        const { selectedIndex } = this.state;
        const buttons = [
            { element: this.tableLabel }, 
            { element: this.chartLabel }, 
            { element: this.detailsLabel }
        ]; console.log("Data : " + JSON.stringify(purchases));

        return (
            <MainView 
                backgroundImageUri={require('../../../assets/images/background_no_line.png')}>
                <MainHeader 
                    title="historique des achats du mois"
                    uri={require('../../../assets/images/purchase.png')}
                    navigation={navigation}
                    containerStyle={{marginTop: '7%'}}
                />
                {isLoading ?
                    <Spinner containerStyle={{marginTop: 150, alignItems: 'center'}} 
                        color="blue" /> :
                    <Fragment>
                        <ScrollView style={styles.contentContainerStyle}>
                        {
                            selectedIndex === 0 ?
                            <PurchaseMonthTable head={tableHead} purchases={purchases} /> :
                            selectedIndex === 1 ? 
                            <PurchaseMonthChart purchases={purchases} /> :
                            <PurchaseMonthDetails />  
                        }
                        </ScrollView>
                        <ButtonGroup 
                            onPress={this._updateIndex}
                            buttons={buttons}
                            buttonStyle={{marginHorizontal: 0}}
                            selectedButtonStyle={{backgroundColor: '#7B7C9E'}}
                            selectedIndex={selectedIndex}
                            containerStyle={styles.tabButtonContainerStyle}
                        />
                    </Fragment>
                }
            </MainView>
        );
    }
}

const styles = StyleSheet.create({
    contentContainerStyle: {
        marginHorizontal: 5,
        flex: 1
    },
    tabButtonContainerStyle: {
        height: 50, 
        justifyContent: 'flex-end', 
        marginLeft: 0,
        marginRight: 0,
        marginBottom: 0
    }
});

PurchaseMonth.defaultProps = {
    purchases: []
};

PurchaseMonth.propTypes = {
    purchases: PropTypes.array
};

const mapstateToProps = (state) => ({
    profile: state.profile,
    isLoading: state.uiLoading.isLoading,
    purchases: state.purchases.purchasesMonth
});

export default connect(mapstateToProps, { getMonthPurchases })(PurchaseMonth);
  • Подкомпонент 1: PurchaseMonthTable
import React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import PropTypes from 'prop-types';
import { Table, TableWrapper, Row } from 'react-native-table-component';
import { isArray } from 'lodash';

const element = (products, index) => (
    <View style={styles.panelBottomStyle}>
        <Text style={{color: '#00151C'}} numberOfLines={5}>
        {isArray(products) ? products.join(" ") : ""}
        </Text>
    </View>
);

const PurchaseMonthTable = (props) => {

    const { head, purchases } = props;

    return (
        <View style={styles.containerStyle}>
            <Table borderStyle={{borderColor: 'transparent'}}>
                <Row data={head} flexArr={[1, 1, 1, 1, 1]} 
                    style={styles.headStyle} textStyle={styles.textStyle}
                />
                {
                    purchases.length > 0 ?
                    purchases.map((rowData, index) => {
                        rowData.unshift(index + 1);
                        const products = rowData.pop();

                        return (
                            <TableWrapper key={index + "".toString()} 
                            style={{marginBottom: 15}}>
                                <Row 
                                    key={"value" + index + "".toString()} 
                                    data={rowData}
                                    textStyle={styles.textStyle}
                                />
                                <Row 
                                    key={"product" + index + "".toString()}
                                    data={[element(products, index)]}
                                />
                            </TableWrapper>
                        )
                    })
                    :
                    <Row style={{marginTop: 50}}
                        data={['Aucune statistique pour ce mois.']}
                        flexArr={[1]} 
                        textStyle={styles.textStyle}
                    />
                }
            </Table>
        </View>
    );

}

PurchaseMonthTable.defaultProps = {
    purchases: []
};

PurchaseMonthTable.propTypes = {
    head: PropTypes.array.isRequired,
    purchases: PropTypes.array
};

const styles = StyleSheet.create({
    containerStyle: {
        flex: 1,
        marginTop: 20
    },
    headStyle: {
        height: 40,  
        backgroundColor: '#7B7C9E'
    },
    textStyle: {
        textAlign: 'center',
        color: 'white'
    },
    panelBottomStyle: {
        backgroundColor: 'white', 
        marginTop: 2, 
        marginHorizontal: 10,
        padding: 5
    }
});

export default PurchaseMonthTable;

  • подкомпонент 2: PurchaseMonthChart
import React from 'react';
import { StyleSheet, View, Dimensions } from 'react-native';
import PropTypes from 'prop-types';

const deviceWidth = Dimensions.get('window').width;

const PurchaseMonthChart = (props) => {

    const { purchases } = props;

    return (
        <View style={styles.containerStyle}>

        </View>
    );
}

PurchaseMonthChart.defaultProps = {
    purchases: []
};

PurchaseMonthChart.propTypes = {
    purchases: PropTypes.array
};

const styles = StyleSheet.create({
    containerStyle: {
        flex: 1,
        marginTop: 50,
        backgroundColor: 'white'
    }
});

export default PurchaseMonthChart;

  • подкомпонент 3:
import React from 'react';
import { StyleSheet, View, FlatList, Text } from 'react-native';

const data = [
    ['BANANA', 15],
    ['POM', 15],
    ['MEAT', 15],
    ['RICE', 15],
    ['KOKI', 15]
];

const _renderItem = ({ item }) => (
    <View style={styles.productContainerStyle}>
        <View style={styles.producTitleStyle}>
            <Text style={{color: 'white'}}>{item[0] + "".toUpperCase()}</Text>
        </View>
        <View><Text style={{color: 'white'}}>{item[1]}</Text></View>
    </View> 
);

const PurchaseMonthDetails = (props) => {

    return (
        <View style={styles.containerStyle}>
            <FlatList 
                renderItem={_renderItem}
                keyExtractor={(item, index) => index.toString()}
                data={data}
            />
        </View>
    );
}

const styles = StyleSheet.create({
    containerStyle: {
        flex: 1,
        marginTop: 20
    },
    productContainerStyle: {
        flexDirection: 'row', 
        marginVertical: 5, 
        marginHorizontal: 10, 
        justifyContent: 'space-between',
        alignItems: 'center'
    },
    producTitleStyle: {
        borderRadius: 10, 
        backgroundColor: '#7B7C9E', 
        width: "40%", 
        height: 40,
        justifyContent: 'center',
        alignItems: 'center'
    }
});

export default PurchaseMonthDetails;

  • action: getMonthPurchases
export const getMonthPurchases = (numero, encryptedPass) => dispatch => {

    dispatch(uiStartLoading());

    if(!isEmpty(encryptedPass)) {
        const password = decryptPass(encryptedPass);

        getPurchases(numero, password, true).then(
            (data) => {
                const dayOfMonth = (new Date()).getDate();

                const purchases = [];
                for(i = 0; i < dayOfMonth; i++) {
                    purchases[i] = [0, 0, 0, 0, []]; 
                }

                data.forEach(element => {
                    switch (element.famille) {
                        case "B1":

                            purchases[element.jour - 1][0] += element.quantite;   
                            break;

                        case "B2":
                            purchases[element.jour - 1][1] += element.quantite;

                            break;

                        case "B3":
                        case "B4":
                            purchases[element.jour - 1][2] += element.quantite;
                            break;

                        default:
                            break;
                    }

                    purchases[element.jour - 1][3] += element.montant;
                    purchases[element.jour - 1][4].push(element.produit);

                });

                dispatch({
                    type: GET_MONTH_PURCHASE,
                    value: purchases
                });

                dispatch(uiStopLoading());

            }
        ).catch((error) => {
            dispatch(uiStopLoading());
            toast(CONNEXION_PROBLEM_MSG, "danger", 10000);
        });

    } else {
        dispatch(uiStopLoading());
    }

}
  • Редуктор: покупки редуктор
import { 
    GET_MONTH_PURCHASE, 
    GET_YEAR_PURCHASE, 
} from "../actions/types";

const initialState = {
    purchasesMonth: [],
    purchasesYear: [],
    products: []
};

export default function(state = initialState, action) {
    let newState; 

    switch (action.type) {
        case GET_MONTH_PURCHASE:
            newState = {
                ...state,
                purchasesMonth: action.value
            }    
            break;

        case GET_YEAR_PURCHASE:
            newState = {
                ...state,
                purchasesYear: action.value
            }    
            break;   

        default:
            newState = state;
            break;
    }

    return newState || state;
}

Для отладки я использую собственный встроенный отладчик, чтобы получить этот снимок экрана (генерируется консольным журналом в родительском компоненте PurchaseMonth):

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...