Redux connect mapStatetoProps получить пустое состояние - PullRequest
0 голосов
/ 04 апреля 2020

Я изменяю старую версию проекта response + redux side, поскольку бэкэнда нет, я могу только имитировать api resopnd.

Проблема, с которой я столкнулся, состоит в том, что у меня есть домашний интеллектуальный компонент, который будет имитировать 2 действия API вызова, getHomeAllData и getProfileAllData в течение цикла componentDidMount,

Все процессы API вызова и редуктора являются нормальными, и журнал также отображается правильно, но 2 реквизита, которые должны быть получены в Цикл дома getDerivedStateFromProps всегда будет на 1 меньше. Через журнал я обнаружил, что когда на редукс-коннект получено 2 редуктора, при возврате состояния один из mapStatetoProps станет пустым объектом, и сообщение об ошибке не появится. Если он не будет выполнен в одно и то же время, каждый вызов сможет нормально получать повторное открытие, что меня очень смущает.

combReducers не может обработать состояние соединения, возвращаемое одновременно? Или что-то не так с моей конфигурацией?

Прикрепите мой код, надеюсь, каждый сможет помочь, благодарен.

Домашний контейнер

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {HomeRedux, ProfileRedux} from '../../Redux/Modules';


class Home extends Component {

    constructor() {
        super();
        this.state = {
            getHomeRecommendStatus: false,
            getProfileChannelStatus: false,
            homeRecommendData: [],
            profileChannelData: [],
        };
    }

    componentDidMount() {
        this.getHomeAllData();
        this.getProfileAllData();
    }

    static getDerivedStateFromProps(nextProps) {
        switch (nextProps.action.type) {
            case HomeRedux.HomeRecommendActions.getHomeRecommendSuccess:
                return {getHomeRecommendStatus: true, homeRecommendData: nextProps.action.payload.items};

            case ProfileRedux.ProfileChannelActions.getProfileChannelDataSuccess:
                return {getProfileChannelStatus: true, profileChannelData: nextProps.action.payload.items};

            default:
                break;
        }

        return null;
    }

    getHomeAllData = () => {
        this.props.HomeActionsCreator.simulationGetHomeData(request);
    };

    getProfileAllData = () => {
        this.props.ProfileActionsCreator.simulationGetProfileData(request);
    };

    render() {
        return (
            <div>
                <HomeView>
                    <ContentArea>
                        {
                            this.state.getHomeRecommendStatus && this.state.getProfileChannelStatus
                                ? this.state.homeRecommendData.map((item) => {
                                    return (
                                        <VideoItem
                                            key={item.id}
                                            videoItemData={item}
                                            itemClickAction={this.videoItemClick}
                                        />
                                    );
                                })
                                : <UserActionResult userActionResultData={userActionResultData}/>
                        }
                    </ContentArea>
                </HomeView>
            </div>
        );
    }
}

Home.propTypes = {
    HomeActionsCreator: PropTypes.object.isRequired,
    PlayActionsCreator: PropTypes.object.isRequired,
};

export default connect(
    // Every time the second state received here is empty {}
    (state) => {
        return {action: state.HomeReducer.action};
    },
    (dispatch) => {
        return {
            HomeActionsCreator: bindActionCreators(HomeRedux.HomeActionsCreator, dispatch),
            ProfileActionsCreator: bindActionCreators(ProfileRedux.ProfileActionsCreator, dispatch)
        };
    }
)(Home);

Home Redux

import {createAction} from 'redux-actions';
import {ProfileRedux} from '../../../Redux/Modules';
import ApiSimulation from '../../../ApiCenter/Api/ApiSimulation';

export const HomeRecommendActions = {
    getHomeRecommendStart: 'GET_HOME_RECOMMEND_START',
    getHomeRecommendSuccess: 'GET_HOME_RECOMMEND_SUCCESS',
    getHomeRecommendFailed: 'GET_HOME_RECOMMEND_FAILED',
};

const simulationGetHomeData = () => {
    return (dispatch) => {
        dispatch(createAction(HomeRecommendActions.getHomeRecommendStart)());
        dispatch(createAction(HomeRecommendActions.getHomeRecommendSuccess)(ApiSimulation.getSearchHome()));
    };
};

export const HomeActionsCreator = {
    simulationGetHomeData,
};

export default function HomeReducer(state = {action: ''}, action) {
    // Both success actions received here are normal, there is respond data
    switch (action.type) {
        case HomeRecommendActions.getHomeRecommendSuccess:
        case HomeRecommendActions.getHomeRecommendFailed:
        case ProfileRedux.ProfileChannelActions.getProfileChannelDataSuccess:
        case ProfileRedux.ProfileChannelActions.getProfileChannelDataFailed:
            return {action: action};

        default:
            return state;
    }
}

Профиль Redux

import {createAction} from 'redux-actions';
import ApiSimulation from '../../../ApiCenter/Api/ApiSimulation';

export const ProfileChannelActions = {
    getProfileChannelDataStart: 'GET_PROFILE_CHANNEL_DATA_START',
    getProfileChannelDataSuccess: 'GET_PROFILE_CHANNEL_DATA_SUCCESS',
    getProfileChannelDataFailed: 'GET_PROFILE_CHANNEL_DATA_FAILED',
};

const simulationGetProfileData = () => {
    return (dispatch) => {
        dispatch(createAction(ProfileChannelActions.getProfileChannelDataStart)());
        dispatch(createAction(ProfileChannelActions.getProfileChannelDataSuccess)(ApiSimulation.getChannels()));
    };
};


export const ProfileActionsCreator = {
    simulationGetProfileData
};

export default function ProfileReducer(state = {action: ''}, action) {
    switch (action.type) {
        case ProfileChannelActions.getProfileChannelDataSuccess:
        case ProfileChannelActions.getProfileChannelDataFailed:
            return {action: action};

        default:
            return state;
    }
}

Api Simulation

const simulationHome = {
    some data...
};

const simulationChannels = {
    some data...
};

export default class ApiSimulation {
    static getSearchHome() {
        return simulationHome;
    }

    static getChannels() {
        return simulationChannels;
    }

}

Комбинированные редукторы

import {combineReducers} from 'redux';
import ProfileReducer from '../Redux/Modules/Profile/ProfileRedux';
import HomeReducer from '../Redux/Modules/Home/HomeRedux';

const RootReducer = combineReducers({
    ProfileReducer,
    HomeReducer,
});

export default RootReducer;

Redux Store

import {createStore, applyMiddleware} from 'redux';
import reduxThunk from 'redux-thunk';
import RootReducer from '../Redux/RootReducer';

const ReduxStore = createStore(RootReducer, applyMiddleware(reduxThunk));

export default ReduxStore;

Страница загружается

I Использовали реактивную нагрузку

import React from 'react';
import Loadable from 'react-loadable';

const LoadingPage = () => {
    return (<div>Loading...</div>);
};

export const Home = Loadable({
    loader: () => import('./Containers/Home/Home'),
    loading: LoadingPage
});

Root index

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import createHistory from 'history/createHashHistory';
import ReduxStore from './Redux/ReduxStore';
import {render} from 'react-dom';
import {Provider} from 'react-redux';
import {HashRouter, Router, Switch, Route} from 'react-router-dom';
import {Home} from './page-loadable';
import {Portal} from '../src/Containers/index';
import {Header, ActionAlert} from './Components/Layout';

const History = createHistory();
const CommonLayout = React.createContext({path: ''});

class CommonLayoutProvider extends Component {
    render() {
        return (
            <CommonLayout.Provider>
                <Header/>
                <ActionAlert/>
                {this.props.children}
            </CommonLayout.Provider>
        );
    }
}

CommonLayoutProvider.propTypes = {
    children: PropTypes.object.isRequired
};

render((
    <Provider store={ReduxStore}>
        <HashRouter>
            <Router history={History}>
                <div style={{width: '100%', height: '100%'}}>
                    <Route component={Portal}/>
                    <Switch>
                        <CommonLayoutProvider>
                            <Route path='/home' component={Home}/>
                        </CommonLayoutProvider>
                    </Switch>
                </div>
            </Router>
        </HashRouter>
    </Provider>
), document.getElementById('app'));

Package. json

{
  "name": "",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack -p",
    "clean": "rimraf dist/*",
    "dev": "webpack-dev-server --devtool eval --progress --watch --hot --mode production",
    "prd": "npm run clean && webpack --mode production"
  },
  "author": "Hsien",
  "license": "ISC",
  "dependencies": {
    "@ant-design/icons": "latest",
    "@types/gapi.client": "^1.0.1",
    "antd": "^3.22.0",
    "axios": "^0.18.0",
    "final-form": "^4.12.0",
    "gapi-client": "0.0.3",
    "history": "^4.7.2",
    "is_js": "^0.9.0",
    "moment": "^2.24.0",
    "prop-types": "^15.6.2",
    "react": "^16.4.2",
    "react-dom": "^16.4.2",
    "react-google-authorize": "^1.0.4",
    "react-loadable": "^5.5.0",
    "react-player": "^1.11.0",
    "react-redux": "^5.0.7",
    "react-router": "^4.3.1",
    "react-router-dom": "^4.3.1",
    "react-router-redux": "^4.0.8",
    "redux": "^4.0.0",
    "redux-actions": "^2.6.1",
    "redux-thunk": "^2.3.0",
    "styled-components": "^3.4.6",
    "webpack-hashed-module-id-plugin": "^0.1.4"
  },
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-eslint": "^9.0.0",
    "babel-loader": "^7.1.5",
    "babel-plugin-import": "^1.12.2",
    "babel-plugin-transform-decorators-legacy": "^1.3.5",
    "babel-plugin-transform-react-jsx": "^6.24.1",
    "babel-preset-env": "^1.7.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1",
    "brotli-webpack-plugin": "^1.1.0",
    "clean-webpack-plugin": "^0.1.19",
    "compression-webpack-plugin": "^2.0.0",
    "css-loader": "^1.0.0",
    "eslint": "^5.5.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-loader": "^2.1.0",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-react": "^7.11.1",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^2.0.0",
    "hard-source-webpack-plugin": "^0.13.1",
    "html-webpack-plugin": "^3.2.0",
    "mini-css-extract-plugin": "^0.4.5",
    "moment-locales-webpack-plugin": "^1.1.0",
    "node-sass": "^4.9.3",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "style-ext-html-webpack-plugin": "^3.4.7",
    "style-loader": "^0.23.0",
    "uglifyjs-webpack-plugin": "^1.3.0",
    "url-loader": "^1.1.1",
    "webpack": "^4.17.1",
    "webpack-bundle-analyzer": "^3.6.0",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.7"
  }
}
...