组件的prop不会在React Native中使用Redux进行更新

时间:2017-07-23 22:52:51

标签: react-native redux react-redux react-navigation

我的应用程序和Redux需要一些帮助! (目前,我讨厌它啊)

所以,我有一个获取一些数据的通知页面组件,我需要将数据长度放入我的redux商店,以便在我的标签栏中将徽章放在我的图标上!

我的主要减速机:

import { combineReducers } from "redux";
import NotificationReducer from "./NotificationReducer";

export default function getRootReducer(navReducer) {
    return combineReducers({
        nav: navReducer,
        notificationReducer: NotificationReducer
    });
}

我的通知缩减器

const initialState = {
    NotificationCount: 0
};

export default function notifications(state = initialState, action = {}) {
    switch (action.type) {
        case 'SET_COUNT' :
            console.log('REDUCER NOTIFICATION SET_COUNT',state)
            return {
                ...state,
                NotificationCount: action.payload
            };

        default:
            return state;
    }
};

我的行动:

export function setNotificationCount(count) {
    return function (dispatch, getState) {
          console.log('Action - setNotificationCount: '+count)
          dispatch( {
            type: 'SET_COUNT',
            payload: count,
          });
    };
};

我的组件:

import React, { Component } from 'react';
import { View, Text, StyleSheet, ScrollView, Dimensions, TouchableOpacity, SectionList, Alert } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import { Notification } from '@Components';
import { ORANGE } from '@Theme/colors';
import { NotificationService } from '@Services';
import Style from './style';

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '@Redux/Actions';

const width = Dimensions.get('window').width
const height = Dimensions.get('window').height

export class NotificationsClass extends Component {

    constructor(props) {
        super(props);
        this.state = {
            dataSource: [],
            NotificationCount: undefined
        };
    }

    async componentWillMount() {
        this.updateNotifications();
    }

    componentWillReceiveProps(nextProps){
        console.log('receive new props',nextProps);
    }

    async updateNotifications() {
        this.props.setNotificationCount(10); <---
        let data = await NotificationService.get();
        if (data && data.data.length > 0) {
            this.setState({ dataSource: data });
            console.log(this.props) <-- NotificationCount is undefined
        }
    }


    render() {
        if (this.state.dataSource.length > 0) {
            return (
                <SectionList
                    stickySectionHeadersEnabled
                    refreshing
                    keyExtractor={(item, index) => item.notificationId}
                    style={Style.container}
                    sections={this.state.dataSource}
                    renderItem={({ item }) => this.renderRow(item)}
                    renderSectionHeader={({ section }) => this.renderSection(section)}
                />
            );
        } else {
            return this.renderEmpty();
        }
    }

    renderRow(data) {
        return (
            <TouchableOpacity activeOpacity={0.8} key={data.notificationId}>
                <Notification data={data} />
            </TouchableOpacity>
        );
    }


}


const Notifications = connect(
    state => ({
        NotificationCount: state.NotificationCount
    }),
    dispatch => bindActionCreators(Actions, dispatch)
)(NotificationsClass);


export { Notifications };

(我删除了一些无用的代码)

顶级:

const navReducer = (state, action) => {
    const newState = AppNavigator.router.getStateForAction(action, state);
    return newState || state;
};

@connect(state => ({
    nav: state.nav
}))
class AppWithNavigationState extends Component {
    render() {
        return (
            <AppNavigator
                navigation={addNavigationHelpers({
                    dispatch: this.props.dispatch,
                    state: this.props.nav,
                })}
            />
        );
    }
}

const store = getStore(navReducer);

export default function NCAP() {
    return (
        <Provider store={store}>
            <AppWithNavigationState />
        </Provider>
    );
}

反应:15.6.1 React-Native:0.46.4 Redux:3.7.2 React-Redux:5.0.5 React-Navigation:1.0.0-beta.11 节点:6.9.1

所以如果你有个主意!这将是伟大的:D!

谢谢!

1 个答案:

答案 0 :(得分:1)

有三个问题。

首先,React的重新渲染几乎总是异步的。在updateNotifications()中,您正在调用this.props.setNotificationCount(10),但稍后尝试在该函数中查看/使用道具。即使有await,也无法保证this.props.NotificationCount尚未更新。

其次,根据您的reducer结构和mapState函数,props.NotificationCount实际上永远不会存在。在getRootReducer()函数中,您有:

return combineReducers({
    nav: navReducer,
    notificationReducer: NotificationReducer
});

这意味着您的根状态将是state.navstate.notificationReducer。但是,在mapState函数中,您有:

state => ({
    NotificationCount: state.NotificationCount
}),

state.NotificationCount永远不会存在,因为您在调用combineReducers时没有使用该键名。

第三,你的notificationReducer实际上有一个嵌套值。它正在返回{NotificationCount : 0}

所以,你真正想要的价值实际上是state.notificationReducer.NotificationCount。这意味着您的mapState函数实际应该是:

state => ({
    NotificationCount: state.notificationReducer.NotificationCount
}),

如果您的notificationReducer实际上并不存储任何其他值,我建议将其简化为只存储数字,而不是存储对象内部的数字。我还建议从状态切片名称中删除单词Reducer。这样,您可以改为引用state.notification

有关详细信息,请参阅Redux文档的Structuring Reducers - Using combineReducers部分,其中详细介绍了如何使用combineReducers定义状态形状。