组件的 prop 不会在 React Native 和 Redux 中更新

Component's prop doesn't update in React Native with Redux

我的应用程序和 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 反应本机:0.46.4 终极版:3.7.2 反应终极版:5.0.5 反应导航:1.0.0-beta.11 节点:6.9.1

所以,如果您有想法!这会很棒 :D !

谢谢!

存在三个问题。

首先,React 的重新渲染几乎总是异步的。在 updateNotifications() 中,您正在调用 this.props.setNotificationCount(10),但稍后会尝试 view/use 该函数中的道具。即使 await 在那里,也不能保证 this.props.NotificationCount 会被更新。

其次,根据您的减速器结构和 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 定义状态形状。