每次我导航离开并返回屏幕时,Redux 或 RNRF 递增渲染 3-4

Redux or RNRF incrementing renders by 3-4 every-time i navigate away and comeback to screen

我认为这可能是一个 redux 问题,但我开始怀疑这是否与导航堆栈有关..

我正在尝试通过 firebase 加载与不同人的一些聊天。首次加载时,一切正常。但是,如果我点击聊天,发送一个 'text' 到 firebase 并导航回聊天列表屏幕,我注意到在控制台中,每次我离开然后回来时,屏幕都会被渲染 3-4 次背部。来回运行一段时间后,屏幕可能会在完成前渲染 50 次。显然对 UI.

有很大的拖累

在这种情况下,我可以使用下拉刷新进行重现。它应该在更改时更新 UI 并渲染 2-3 次,或者通过减速器中的匹配不执行任何操作。但它几乎总是在 ~3-4

的渲染中递增

我花了好几个小时弄乱 redux 看看我是否做错了什么,但我想知道从 Firebase 返回的新数据是否正在更新堆栈中的每个视图?

我尝试使用 Actions.reset('scene') 方法,但如果我将其用作收件箱的入口点,则会引发错误。我什至在我的路由器场景中尝试过 type=ActionsConst.RESET 但它似乎不再有效(仅替换)。

我现在很茫然。任何帮助将不胜感激。

RN:0.58.5 RNRF:4.0.6 React-Redux:6.0.1

Messages.js

class Messages extends Component {

constructor(props){
    super(props);
    console.log(props);

}

async componentDidMount() {
    console.log('messages mounted');
    const user_id = this.props.user_id;
    await this.props.getFBKeys({ promoter_id });
    await this.openFirebase();

}

componentWillUnmount() {
    console.log('inbox unmounted');
}

openFirebase(){

    console.log('starting openFirebase');

    let dataArr = [];
    let counter = 0;

    for (let i = 0; i < this.props.firebaseKeys.length; i++) {

        ref.child(`/${this.props.firebaseKeys[i]}`).once("value", (snapshot) => {

            const snapshotKey = snapshot.key;
            const snapshotVal = snapshot.val();
            const data = { [snapshotKey] : snapshotVal };

            dataArr.push(data);

            counter++;

            if (counter === this.props.firebaseKeys.length){
                this.props.getListOfChats({dataArr});
                console.log("setting state");
            }
            });
        }
    }


    _onRefresh = () => {

        Actions.Inbox({type: ActionConst.RESET});
        // also tried Actions.reset('Inbox'); & Actions.reset({sceneKey: 'Inbox', index: 0});
        this.openFirebase();

    };

    renderDataOrErrorState(){
        if (this.props.loadingData){
            console.log('hit 1');
            return <Spinner/>;

        } else {

            if (!this.props.listOfChats){
                console.log('hit 2');
                return <ErrorComponent errorText='You dont have any messages' iconSize={140}/>
            } else {
                console.log('hit 3');
                return (
                    <FlatList
                        data={this.props.listOfChats}
                        // extraData={this.state.chatThread}
                        renderItem={({item}) => <MessagePreview item={item}/>}
                        keyExtractor={(item, index) => 'key'+index}
                    />
                )
            }
        }

    }


    render() {

        console.count(' MESSAGES counter');
        return (
            <View style={styles.container}>
                <StandardToolbar titleText="INBOX"/>
                <ScrollView
                    refreshControl={
                        <RefreshControl
                            refreshing={false}
                            onRefresh={this._onRefresh}
                        />
                    }
                >
                    {this.renderDataOrErrorState()}

                </ScrollView>
            </View>
        )
    }
}

const styles = {

    container: {
        flex: 1,
        backgroundColor: '#fff',
    },

    spaceBetween: {
        margin: 10
    },

    marginBottom: {
        marginBottom: 70
    }

};

const mapStateToProps = ({ loggedInUser, messagesReducer }) => {

    const { firebaseKeys, loadingData, listOfChats} = messagesReducer;

    const { user_id } = loggedInUser;

    return { firebaseKeys, promoter_id, loadingData, listOfChats };

};

export default connect(mapStateToProps, {
    getFBKeys,
    getListOfChats,
    updateListOfChats
})(Messages);

MessagesActions.js

import {
    MAIN_BASE_URL,
    GET_FIREBASE_KEYS,
    NO_FIREBASE_KEYS,
    GET_LIST_OF_CHATS,
    UPDATE_LIST_OF_CHATS,
    UPDATE_FALSE
} from "../../actions/types";

import axios from 'axios';


export const getFBKeys = ({ user_id }) => {

    return (dispatch) => {

        return axios.get(`Main/Url/To/Get/Data`, {
            params: {
                user_id: user_id,
            }
        }).then((response) => {
            // console.log(response.data.length);

            if (response.data.length === 0){

                dispatch({type: NO_FIREBASE_KEYS });

            } else {

                dispatch({type: GET_FIREBASE_KEYS, payload: response.data });

            }

        }).catch((error) => {
            console.log(JSON.stringify(error));
        })
    }
};

export const getListOfChats = ({dataArr}) => {

    return (dispatch) => {
        dispatch({
            type: GET_LIST_OF_CHATS,
            payload: dataArr
        });
    }

};

MessagesReducer.js

import {
    GET_FIREBASE_KEYS,
    NO_FIREBASE_KEYS,
    GET_LIST_OF_CHATS,
} from "../../actions/types";

import _ from 'lodash';

const INITIAL_STATE = {
    listOfChats: [],
    firebaseKeys: [],
    loadingData: true,
};


export default (state = INITIAL_STATE, action) => {
    switch (action.type) {

        case GET_FIREBASE_KEYS:

            if (JSON.stringify(action.payload) === JSON.stringify(state.firebaseKeys)){

                return Object.assign({}, state);

            } else {
                return Object.assign({}, state, {
                    firebaseKeys: action.payload,
                    loadingData: false
                });
            }

        case NO_FIREBASE_KEYS:

            return Object.assign({}, state, {
                loadingData: false
            });

        case GET_LIST_OF_CHATS:

            if (_.isEqual(action.payload, state.listOfChats)){
                console.log('chat state equal. returning state');

                return Object.assign({}, state);

            } else {
                console.log('returning new chats');

                return Object.assign({}, state, {
                    loadingData: false,
                    listOfChats: action.payload

                });
            }

        default:
            return state;
    }
}

Router.js

    <Router>
        <Scene key='root' hideNavBar={true}>

            {/* Controls main TabBar */}
            <Tabs
                key="TabBar"
                tabBarPosition="bottom"
                tabBarComponent={TabBar}
            >
                <Scene
                    key='Home'
                    hideNavBar={true}
                    initial

                >
                    <Scene
                        key='Main'
                        hideNavBar={true}
                        initial
                    >
                        <Scene
                            key='homeScreen'
                            hideNavBar={true}
                            component={HomeScreen}
                            title='Home'
                            initial
                        />
                        <Scene
                            key='CustomerProfile'
                            hideNavBar={true}
                            component={CustomerProfile}
                            title='Customer Profile'
                        />

                        <Scene
                            key='CustomerSearch'
                            hideNavBar={true}
                            component={CustomerSearch}
                            title='Customer Search'
                        />

                        <Scene
                            key='WriteAReview'
                            hideNavBar={true}
                            component={WriteAReview}
                            title='Write A Review'
                        />

                        <Scene
                            key='ReviewsHome'
                            hideNavBar={true}
                            component={ReviewsHome}
                            title='Reviews'
                        />
                    </Scene>

                    <Scene
                        key="Camera"
                        component={Scanner}
                        title="QRCodeScanner"
                        hideNavBar={true}
                        hideTabBar={true}


                    />

                    <Scene
                        key='Inbox'
                        component={Messages}
                        title='Inbox'
                        hideNavBar={true}
                        // tried this as well --> type={ActionsConst.RESET}

                    />

                    <Scene
                        key='Text'
                        component={FullText}
                        title='Text'
                        hideNavBar={true}
                        hideTabBar={true}
                        // type='replace'



                    />

                    <Scene
                        key='GL'
                        component={GL}
                        title='GL'
                        hideNavBar={true}
                    />

                    <Scene
                        key='STA'
                        component={STA}
                        title='Your STA'
                        hideNavBar={true}
                    />

                    <Scene
                        key="PubProf"
                        hideNavBar={true}
                    >
                        <Scene
                            key="Profile"
                            component={Profile}
                            title="Profile"
                            hideNavBar={true}
                            initial
                        />
                        <Scene
                            key='PublicProfile'
                            component={PublicProfile}
                            title='Public Profile'
                            hideNavBar={false}
                        />

                    </Scene>
                </Scene>
            </Tabs>
        </Scene>
    </Router>

天哪,我想通了。出于一些愚蠢的原因,我将标签栏中的所有场景都包裹在一个名为 'Home' 的父场景中。删除它会停止所有不必要的渲染。赞美主