簡體   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

在我的app componentDidMount中,我簡單地調用了redux。 數據通過api獲取並設置到商店。 當從reducer中記錄數據時,它就在那里,但由於某種原因,即使道具應該被更改,我的App組件也不會更新。

有點無能為力,我在這里失蹤,任何幫助將不勝感激。

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

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:

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;

渲染周期截圖: 在此輸入圖像描述

在此輸入圖像描述

您正在訪問錯誤的數據

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

您的reducer名稱是currentUserReducer,因此您的mapStateToProps應該是這樣的。

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

事實證明,redux運作良好。 但我在componentDidMount中記錄數據,這意味着只有在第一次安裝組件時...將其更改為willupdate方法並且工作正常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM