单击当前链接页面后,太多的重新渲染响应redux

时间:2019-10-23 21:34:39

标签: reactjs redux react-redux

我将redux与react JS一起使用时代码正常工作,但是单击当前页面链接后出现问题

Too many re-renders. React limits the number of renders to prevent an infinite loop.

我尝试解决此问题,但是我不知道为什么在执行任何动作响应后都会执行调度功能, 如果链接等于当前页面,如何停止渲染或阻止重定向

  

减速器

const initState = {
    isFetching: false,
    isSuccess: false,
}

const tableReducer = (state = initState, action) => {
    switch (action.type) {

        case "GET_CONTENT_PENDING": {
            return {...state, isFetching: false, isSuccess: false,}
            break;
        }
        case "GET_CONTENT_REJECTED": {
            return {...state, error: action.payload, isFetching: false, isSuccess: false,}
            break;
        }
        case "GET_RESTORANT_FULFILLED": {
            return {
                ...state,
                isFetching: true,
                isSuccess: true,
                moreRestaurents: action.payload.moreRestaurents,
                restaurent: action.payload.details
            }
            break;
        }
        case "GET_CITIES_FULFILLED": {
            return {...state, isFetching: true, isSuccess: true, cities: action.payload.cities}
            break;
        }
        case "GET_RESTO_GROUP_BY_CITY_FULFILLED": {
            return {
                ...state,
                isFetching: true,
                isSuccess: true,
                restaurantsGroupedBySity: action.payload.restaurantsGroupedBySity
            }
            break;
        }
        case "GET_CITY_RESTORANTS_FULFILLED": {
            return {
                ...state,
                isFetching: true,
                isSuccess: true,
                cityRestaurents: action.payload.cityRestaurents,
                city: action.payload.city
            }
            break;
        }
        case "GET_MOST_RESERVED_FULFILLED": {
            return {
                ...state,
                isFetching: true,
                isSuccess: true,
                mostReservedRestaurents: action.payload.mostReservedRestaurents
            }
            break;
        }
        case "GET_TOP_RESTORANTS_FULFILLED": {
            return {...state, isFetching: true, isSuccess: true, topRestaurents: action.payload.topRestaurents}
            break;
        }
        case "GET_ALL_RESTORANTS_FULFILLED": {
            return {...state, isFetching: true, isSuccess: true, allRestaurents: action.payload.allRestaurents}
            break;
        }
        case "GET_CONTENT_FULFILLED": {
            return {
                ...state,
                isSuccess: true,
                isFetching: true,
                content: action.payload.content,
                page: action.payload.page
            }
            break;
        }
    }
    return state;
}
export default tableReducer;
  

主页组件

export class Home extends Component {
    render() {
        var cities = this.props.homeState.cities;
        var content = this.props.homeState.content;
        var isSuccess = this.props.homeState.isSuccess;
        var isFetching = this.props.homeState.isFetching;
        var page = this.props.homeState.page == "/home";
        var restaurantsGroupedBySity = this.props.homeState.restaurantsGroupedBySity;

        if (isFetching && isSuccess && cities && content && restaurantsGroupedBySity && page) {
            var cities = this.props.homeState.cities;
            var content = this.props.homeState.content;
            var isSuccess = this.props.homeState.isSuccess;
            var isFetching = this.props.homeState.isFetching;
            var page = this.props.homeState.page == "/home";
            var restaurantsGroupedBySity = this.props.homeState.restaurantsGroupedBySity;

            if (isFetching && isSuccess && cities && content && restaurantsGroupedBySity && page) {
                return (
            } else {
                return (
                    <div className="loader">
                        <img src="/media/images/table-loader.svg" alt="" />
                    </div>
                )
            }
        }
    }
}

const mapStateToProps = (state) => {
    return {
        homeState: state
    }
}

const mapDispatchToProps = (dispatch, ownProps) => {
    return {
        getCities: getCities(dispatch),
        pageContent: pageContent(dispatch, ownProps.match.path),
        getRestaurantsGroupedByCity: getRestaurantsGroupedByCity(dispatch)
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(Home)
  

动作

import axios from 'axios';

export  const getCities =(dispatch)=> {
        let citiesQuery = '/api/get/cities';
        axios.all([
            axios.get(citiesQuery)
        ]).then(axios.spread((cities) => {
            return dispatch({ type: "GET_CITIES_FULFILLED", payload: { cities: cities.data}})
        })).catch (err => {
            return dispatch({ type: "GET_CONTENT_REJECTED", payload: err })
        }); 

        return dispatch({ type: "GET_CONTENT_PENDING"})
}
export const getRestaurantsGroupedByCity =(dispatch)=> {
        let restaurantsQuery = '/api/get/restaurants-group-by-city';
        axios.all([
            axios.get(restaurantsQuery),
        ]).then(axios.spread((response) => {
            return dispatch({ type: "GET_RESTO_GROUP_BY_CITY_FULFILLED", payload: { restaurantsGroupedBySity: response.data}})
        })).catch (err => {
            return dispatch({ type: "GET_CONTENT_REJECTED", payload: err })
        }); 

        return dispatch({ type: "GET_CONTENT_PENDING"})
}

1 个答案:

答案 0 :(得分:1)

我在您的代码中看到两个问题。

第一个是Home组件中的语法错误:

// ...
if (isFetching && isSuccess && cities && content && restaurantsGroupedBySity && page) {
    // HERE IS SYNTAX ERROR, did you copy your code correctly?
    return (
} else {
// ...

第二个是mapDispatchToProps,为什么没有这么做according to the documentation。我看不到您的动作创建者,但通常应该是这样的:

const mapDispatchToProps = (dispatch, ownProps) => {
    return {
        getCities: (/* action creator args, if any */) =>
            dispatch(getCities(/* action creator args, if any */)),
        pageContent: (/* action creator args, if any */) =>
            dispatch(pageContent(/* action creator args, if any */)),
        getRestaurantsGroupedByCity: (/* action creator args, if any */) =>
            dispatch(getRestaurantsGroupedByCity(/* action creator args, if any */)),
    };
}

甚至最好不要使用mapDispatchToProps,只需输入object into second argument of connect

export default connect(
    mapStateToProps,
    {getCities, pageContent, getRestaurantsGroupedByCity}
)(Home)

编辑(添加动作创建者的源代码之后):

在使用异步操作创建者时,应将redux-thunk(或redux-saga,但thunk对于初学者来说更简单)中间件添加到redux配置中。 然后,您应该以这种方式重写动作创建者(请参见redux-thunk documentaion的详细信息):

import axios from 'axios';

export const getCities = () => (
    (dispatch) => {
        let citiesQuery = '/api/get/cities';
        axios.all([
            axios.get(citiesQuery)
        ]).then(axios.spread((cities) => {
            return dispatch({type: "GET_CITIES_FULFILLED", payload: {cities: cities.data}})
        })).catch(err => {
            return dispatch({type: "GET_CONTENT_REJECTED", payload: err})
        });

        return dispatch({type: "GET_CONTENT_PENDING"})
    }
)

export const getRestaurantsGroupedByCity = () => (
    (dispatch) => {
        let restaurantsQuery = '/api/get/restaurants-group-by-city';
        axios.all([
            axios.get(restaurantsQuery),
        ]).then(axios.spread((response) => {
            return dispatch({
                type: "GET_RESTO_GROUP_BY_CITY_FULFILLED",
                payload: {restaurantsGroupedBySity: response.data}
            })
        })).catch(err => {
            return dispatch({type: "GET_CONTENT_REJECTED", payload: err})
        });

        return dispatch({type: "GET_CONTENT_PENDING"})
    }
)

可读性改进:

尝试使用对象分解,您的代码将更易读(更短)。

首页(顶部)

此:

var cities = this.props.homeState.cities;
var content = this.props.homeState.content;
var isSuccess = this.props.homeState.isSuccess;
var isFetching = this.props.homeState.isFetching;
var page = this.props.homeState.page == "/home";
var restaurantsGroupedBySity = this.props.homeState.restaurantsGroupedBySity;

if (isFetching && isSuccess && cities && content && restaurantsGroupedBySity && page) {
    var cities = this.props.homeState.cities;
    var content = this.props.homeState.content;
    var isSuccess = this.props.homeState.isSuccess;
    var isFetching = this.props.homeState.isFetching;
    var page = this.props.homeState.page == "/home";
    var restaurantsGroupedBySity = this.props.homeState.restaurantsGroupedBySity;

可以这样写:

const {homeState} = this.props;
const {cities, content, isSuccess, isFetching, page, restaurantsGroupedBySity} = homeState;
const isPage = page == "/home"; // I suggest to use '===' operator here

if (isFetching && isSuccess && cities && content && restaurantsGroupedBySity && isPage) {
    // you should not declare the same variables here again,
    // the whole this.props is readonly in whole component and will not change
    // (if so there is an error somewhere)