简体   繁体   English

React + redux,组件通过redux-thunk获取数据并订阅它,但道具在更改时不会更新

[英]React + redux, component fetches data via redux-thunk and subscribes to it but the props doesn't update when they change

In my app componentDidMount I make a simple call to redux. 在我的app componentDidMount中,我简单地调用了redux。 the data gets fetched via an api and set to the store. 数据通过api获取并设置到商店。 When logging the data from the reducer it's all there but for some reason my App component doesn't update even though the props should get changed. 当从reducer中记录数据时,它就在那里,但由于某种原因,即使道具应该被更改,我的App组件也不会更新。

Kinda clueless what I am missing here, any help would be appreciated. 有点无能为力,我在这里失踪,任何帮助将不胜感激。

App.js: App.js:

import React, { Component } from "react";

import { library } from "@fortawesome/fontawesome-svg-core";
import { faIgloo, faBars, faUser } from "@fortawesome/free-solid-svg-icons";
import { initializeIcons } from "@uifabric/icons";
import { acquireToken, acquireGraphToken } from "../../adalConfig";

import Navbar from "../../common/navbar/navbar";
import Searchbar from "../../common/utils/searchBar/searchBar";
import LeftNavigation from "../../common/leftNavigation/leftNavigation";
import PageContainer from "../pageContainer/pageContainer";
import { IntlProvider } from "react-intl";

import WithLoading from "../../common/utils/withLoading";

import messages_en from "../../assets/translations/translations_en";
import messages_nl from "../../assets/translations/translations_nl";
import StylesheetLoader from "../../common/utils/stylesheetLoader/stylesheetLoader";
import ReactAI from "react-appinsights";
import { connect } from "react-redux";
import * as userActions from "../../store/users/actions";
import * as tokenActions from "../../store/tokens/actions";

initializeIcons();
library.add(faIgloo, faBars, faUser);

class App extends Component {
    state = {
        languageChoice: "en",
        theme: "red",
        tokensAreLoaded: false,
        token: ""
    };

    componentDidMount() {
        this.props.onFetchCurrentUser();
        this.props.onFetchTokens();
        console.log("selected language", this.props);
    }

    render() {
        // Sets an interval that refreshes to get the token every 15 minutes
        // We use this because our custom API's do not automatically issue a
        // refresh token.

        setInterval(AppTokenRefresher, 900000);

        function AppTokenRefresher() {
            acquireToken();
            acquireGraphToken();
        }

        let loader = "";

        if (this.props.currentUserLoading) {
            loader = <WithLoading isLoading={true} />;
        }

        const messages = {
            nl: messages_nl,
            en: messages_en
        };

        ReactAI.setAppContext({ urlReferrer: document.referrer });
        // const Ai = ReactAI.ai();

        // function test() {
        //   Ai.trackEvent('Testing', { 'user': 'me' });
        // }

        return (
            <React.Fragment>
                {this.props.currentUser.name}
                {loader == "" ? (
                    <React.Fragment>
                        <StylesheetLoader />
                        <IntlProvider
                            locale={this.state.languageChoice}
                            messages={messages[this.state.languageChoice]}
                        >
                            <div className="siteContainer">
                                <Navbar currentUserProfile={this.props.currentUser} />

                                <div className="mobile-searchbar">
                                    <Searchbar />
                                </div>

                                <div className="page-container">
                                    <aside>
                                        <LeftNavigation />
                                    </aside>

                                    <section className="main">
                                        <PageContainer />
                                    </section>
                                </div>
                            </div>
                        </IntlProvider>
                    </React.Fragment>
                ) : (
                    <div>{loader}</div>
                )}
            </React.Fragment>
        );
    }
}

const mapStateToProps = state => {
    return {
        currentUserError: state.currentUserSlice.currentUserError,
        currentUserLoading: state.currentUserSlice.currentUserLoading,
        currentUser: state.currentUserSlice.currentUser,
        tokensAreLoaded: state.tokensSplice.tokensAreLoaded
    };
};

const mapDispatchToProps = dispatch => {
    return {
        onFetchCurrentUser: () => dispatch(userActions.fetchCurrentUser()),
        onFetchTokens: () => dispatch(tokenActions.fetchRequest())
    };
};

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(App);

Actions.js Actions.js

import { adalOneApiFetch } from "../../adalConfig";
export const FETCH_CURRENT_USER = "FETCH_CURRENT_USER";
export const FETCH_CURRENT_USER_STARTED = "GET_CURRENT_USER_STARTED";
export const FETCH_CURRENT_USER_SUCCESS = "FETCH_CURRENT_USER_SUCCESS";
export const FETCH_CURRENT_USER_FAILURE = "FETCH_CURRENT_USER_FAILURE";

export const fetchRequest = () => {
    return (dispatch, getState) => {
        const currentState = getState();

        dispatch(fetchCurrentUserStarted());

        adalOneApiFetch(
            fetch,
            "https://one365-api-dev.azurewebsites.net/api/me",
            {}
        )
            .then(response => {
                // If the reponse code is not positive, throw an error.
                if (response.status != 200 && response.status != 204) {
                    dispatch(fetchCurrentUserFailure("fout"));
                    return;
                }

                response.json().then(result => {
                    dispatch(fetchCurrentUserSuccess(result));
                });
            })
            .catch(error => {
                dispatch(fetchCurrentUserFailure(error));
            });
    };
};

export const fetchCurrentUserSuccess = users => {
    return {
        type: FETCH_CURRENT_USER_SUCCESS,
        payload: {
            ...users
        }
    };
};

export const fetchCurrentUserStarted = () => ({
    type: FETCH_CURRENT_USER_STARTED
});

export const fetchCurrentUserFailure = error => {
    return {
        type: FETCH_CURRENT_USER_FAILURE,
        payload: {
            error
        }
    };
};

export const fetchCurrentUser = () => {
    return dispatch => {
        dispatch(fetchRequest());
    };
};

reducer.js: reducer.js:

import * as actions from "./actions";

const initialState = {
    currentUserError: "",
    currentUserLoading: false,
    currentUser: []
};

const currentUserReducer = (state = initialState, action) => {
    switch (action.type) {
        case actions.FETCH_CURRENT_USER_STARTED: {
            return {
                ...state,
                loading: (state.currentUserLoading = true)
            };
        }

        case actions.FETCH_CURRENT_USER_SUCCESS: {
            console.log("current user from reducer", action);

            return {
                ...state,
                currentUserLoading: false,
                currentUser: action.payload
            };
        }

        case actions.FETCH_CURRENT_USER_FAILURE: {
            return {
                ...state,
                currentUserLoading: false,
                currentUserError: action.payload.error.message
            };
        }

        default: {
            return state;
        }
    }
};

export default currentUserReducer;

Screenshot of rendering cycle: 渲染周期截图: 在此输入图像描述

在此输入图像描述

You are accessing the wrong data in 您正在访问错误的数据

const mapStateToProps = state => {
    return {
        currentUserError: state.currentUserSlice.currentUserError,
        currentUserLoading: state.currentUserSlice.currentUserLoading,
        currentUser: state.currentUserSlice.currentUser,
        tokensAreLoaded: state.tokensSplice.tokensAreLoaded
    };
};

Your reducer name is currentUserReducer so your mapStateToProps should be like this. 您的reducer名称是currentUserReducer,因此您的mapStateToProps应该是这样的。

const mapStateToProps = state => {
    return {
        currentUser: state.currentUserReducer.currentUser,
    };
};

It actually turned out that redux was working well. 事实证明,redux运作良好。 But I was logging the data in componentDidMount which means only once the component is mounted the first time... changed it to the willupdate method and things were working fine. 但我在componentDidMount中记录数据,这意味着只有在第一次安装组件时...将其更改为willupdate方法并且工作正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM