componentDidUpdate()陷入无限循环

时间:2020-10-20 07:09:13

标签: reactjs react-native

我是新手,可以对本机做出反应,并试图了解React组件的生命周期...我的屏幕上有四个开关。 我试图将开关的当前状态另存为一个对象(应用过滤器),然后将其传递给导航道具的参数,并通过导航标题中保存按钮的onPress函数访问它...

import React, { useState, useEffect, useCallback } from 'react';
import { View, Text, StyleSheet, Switch } from 'react-native';
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
import HeaderButton from '../components/HeaderButton';

const FilterSwitch = (props) => {
  return (
    <View style={styles.filterContainer}>
      <Text>{props.label}</Text>
      <Switch
        value={props.state}
        trackColor={{ true: 'yellow' }}
        thumbColor={{ true: 'blue' }}
        onValueChange={props.onChange}
      />
    </View>
  );
};

class FilterScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGlutenFree: false,
      isLactoseFree: false,
      isVegan: false,
      isVegetarian: false,
    };
    this.setisGlutenFree = this.setisGlutenFree.bind(this);
    this.setisLactoseFree = this.setisLactoseFree.bind(this);
    this.setisVegan = this.setisVegan.bind(this);
    this.setIsVegetarian = this.setIsVegetarian.bind(this);
    this.saveFilters = this.saveFilters.bind(this);
  }
  setisGlutenFree(newValue) {
    this.setState({
      isGlutenFree: newValue,
    });
  }
  setisLactoseFree(newValue) {
    this.setState({
      isLactoseFree: newValue,
    });
  }
  setisVegan(newValue) {
    this.setState({
      isVegan: newValue,
    });
  }
  setIsVegetarian(newValue) {
    this.setState({
      isVegetarian: newValue,
    });
  }
  saveFilters() {
    const appliedFilters = {
      glutenFree: this.state.isGlutenFree,
      lactoseFree: this.state.isLactoseFree,
      vegan: this.state.isVegan,
      Vegetarian: this.state.isVegetarian,
    };
    console.log(appliedFilters);
  }

  componentDidMount() {
    this.props.navigation.setParams({ save: this.saveFilters });
  }
  componentDidUpdate() {
    this.props.navigation.setParams({ save: this.saveFilters });
  }

  render() {
    return (
      <View style={styles.screen}>
        <Text style={styles.title}>Available Filters / Restrictions</Text>
        <FilterSwitch
          label="Gluten-free"
          state={this.state.isGlutenFree}
          onChange={(newValue) => this.setisGlutenFree(newValue)}
        />
        <FilterSwitch
          label="Lactose-free"
          state={this.state.isLactoseFree}
          onChange={(newValue) => this.setisLactoseFree(newValue)}
        />
        <FilterSwitch
          label="Vegan"
          state={this.state.isVegan}
          onChange={(newValue) => this.setisVegan(newValue)}
        />
        <FilterSwitch
          label="Vegetarian"
          state={this.state.isVegetarian}
          onChange={(newValue) => this.setIsVegetarian(newValue)}
        />
      </View>
    );
  }
}

FilterScreen.navigationOptions = (navData) => {
  return {
    headerTitle: 'Filter Meals',
    headerLeft: () => (
      <HeaderButtons HeaderButtonComponent={HeaderButton}>
        <Item
          title="Menu"
          iconName="ios-menu"
          onPress={() => {
            navData.navigation.toggleDrawer();
          }}
        />
      </HeaderButtons>
    ),
    headerRight: () => (
      <HeaderButtons HeaderButtonComponent={HeaderButton}>
        <Item
          title="Save"
          iconName="ios-save"
          onPress={() => {
            console.log('Item Saved');
            console.log(navData.navigation.getParam('save')());
          }}
        />
      </HeaderButtons>
    ),
  };
};

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    alignItems: 'center',
  },
  title: {
    fontFamily: 'open-sans-bold',
    fontSize: 22,
    margin: 20,
    textAlign: 'center',
  },
  filterContainer: {
    marginVertical: 10,
    borderWidth: 1,
    borderRadius: 10,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    width: '80%',
    height: '10%',
    paddingLeft: 10,
  },
});

export default FilterScreen;

问题在于,一旦我们进入筛选器以筛选生命周期方法,该方法就会陷入无限循环....随着大量的堆栈跟踪,以下错误会弹出。

    Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState 
    inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

伙计们,我想每次状态更新时都访问导航标题中组件外部的状态参数...。所以我认为每次组件更新时,导航参数都将获取更新的状态参数

2 个答案:

答案 0 :(得分:1)

每次更新组件时(即状态或道具更改时),都会调用

componentDidUpdate定义。

如果您要更新状态或支持此功能,则会导致无限循环...

答案 1 :(得分:1)

只有在componentDidUpdate中进行了更改时才更新某些内容,以避免无限循环,

componentDidUpdate(prevProps, prevState) {
  if (prevProps.something !== this.props.something) {
    console.log('something  has changed.')
  }
}