Redux存储更新导致HOC中的无限状态重新呈现循环

时间:2018-04-18 03:02:21

标签: reactjs redux infinite-loop dispatch higher-order-components

设置我的第一个react / redux项目。

我正在尝试构建一个Page高阶组件,该组件可以到达外部api以获取页​​面的“框架”:导航,面包屑,通知,标题。由于我有多个页面,我认为这对于HOC来说是一个很好的用例。

这个想法是从api获取数据并将其保存在Redux存储中。每个页面都是一个包含在withPage HOC中的容器。

在我尝试更新redux商店之前,一切正常。更新状态会导致HOC组件和/或包装组件重新呈现,从而导致循环。

让我们看看一些代码,不管吗?

// WrappedComponent

import React, { Fragment, Component } from 'react';
import { connect } from 'react-redux';
import withAuthentication from '../../hoc/withAuthentication';
import withPage from '../../hoc/withPage/withPage';

// import styles from './Welcome.css';

class Welcome extends Component {

    render() {
        return (
            <Fragment>
                <p>Welcome to React!</p>
                <p>Welcome to React!</p>
            </Fragment>
        );
    }
}

const mapStateToProps = state => ( {
    loaded: state.page.loaded,
} );

export default connect( mapStateToProps )( withAuthentication( withPage( Welcome, 187 ) ) );

// withPage HOC

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { fetchPage } from './store';

export default ( ComposedComponent, pageId ) => {
    class Page extends Component {
        componentDidMount() {
            this.props.onPageFetch( this.props.token, pageId );
        }

        render() {
            return <ComposedComponent { ...this.props } />;
        }
    }

    Page.propTypes = {
        onPageFetch: PropTypes.func.isRequired,
    };

    const mapDispatchToProps = dispatch => ( {
        onPageFetch: ( token, id ) => dispatch( fetchPage( token, id ) ),
    } );

    const mapStateToProps = state => ( {
        loaded: state.page.loaded,
    } );

    return connect( mapStateToProps, mapDispatchToProps )( Page );
};

// ducks

import axios from '../../axios-internal';
import { updateObject } from '../../utils/utility';

// ACTIONS
const FETCH_PAGE_START = 'FETCH_PAGE_START';
const FETCH_PAGE_SUCCESS = 'FETCH_PAGE_SUCCESS';
const FETCH_PAGE_FAIL = 'FETCH_PAGE_FAIL';

// ACTION CREATORS
export const fetchPageStart = () => ( {
    type: FETCH_PAGE_START,
} );

export const fetchPageSuccess = ( payload ) => {
    return {
        type: FETCH_PAGE_SUCCESS,
        payload,
    };
};

export const fetchPageFail = error => ( {
    type: FETCH_PAGE_FAIL,
    error,
} );

export const fetchPage = ( token, pageId ) => ( dispatch ) => {
    dispatch( fetchPageStart() );

    axios.get( 'page-187.json' )
        .then( ( res ) => {
            const crumbs = res.data.data.crumbs;
            const page = res.data.data.page;
            const sidebar = res.data.data.sidebar;
            
            // This is introducing the state update loop
            dispatch( fetchPageSuccess( {
                crumbs: crumbs,
                page: page,
                sidebar: sidebar,
            } ) );

        } )
        .catch( ( err ) => {
            dispatch( fetchPageFail( err ) );
        } );
};

// REDUCERS
const initialState = {
    crumbs: null,
    page: null,
    sidebar: null,
    loading: true,
    loaded: false,
};

const helperFetchPageStart = ( state, action ) => updateObject( state, { loading: true } );

const helperFetchPageSuccess = ( state, action ) => updateObject( state, {
    crumbs: action.payload.crumbs,
    page: action.payload.page,
    sidebar: action.payload.sidebar,
    loading: false,
    loaded: true,
} );

const helperFetchPageFail = ( state, actions ) => updateObject( state, { loading: false } );

const reducer = ( state = initialState, action ) => {
    switch ( action.type ) {
        case FETCH_PAGE_START: return helperFetchPageStart( state, action );
        case FETCH_PAGE_SUCCESS: return helperFetchPageSuccess( state, action );
        case FETCH_PAGE_FAIL: return helperFetchPageFail( state, action );
        default: return state;
    }
};

export default reducer;

请注意ducks.js中的注释,指示导致循环的调度操作。

这也可能是对我如何使用HOC的误解。

0 个答案:

没有答案
相关问题