当前位置: 首页 > 知识库问答 >
问题:

反应性:超出最大更新深度错误

蔺劲
2023-03-14

我目前收到Maxiumum更新深度错误,不知道为什么。在我的代码中看不到无限循环

"超过了最大更新深度。当组件在useEffect内部调用setState时,可能会发生这种情况,但useEffect要么没有依赖关系数组,要么其中一个依赖关系在每次渲染时都会发生变化。

此处显示错误

ReactJS组件代码:

import { useNavigation } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import BottomSheet from 'react-native-raw-bottom-sheet';
import React, { useRef } from 'react';
import styled from 'styled-components/native';

import { AnimatedSpinner, Button, ButtonIcon, DropShadow, Block, Row } from '../../../components';
import { BottomTabsType } from '../../../navigation/BottomTabs';
import { Colors } from '../../Theme';
import { useLocation } from '../../../context/location';
import { LocationSheet } from '../LocationSheet';
import Icons from '../../../assets/icons';

type ScreenNavigationProp = StackNavigationProp<BottomTabsType, 'Home'>;

/**
 * Component definition
 */
const LocationButton = styled(Button)`
  backgroundColor:transparent;
  paddingLeft:${Block + 15}px;
  paddingTop:18px;
  color: ${Colors.GreyDark};
  fontFamily: Poppins-Regular;
  fontSize:12px;
`

const SearchButton = styled(ButtonIcon)`
  width:40px;
  height:40px;
  alignItems:center;
  justifyContent:center;
  paddingRight:20px;
`


const Container = styled(Row)`
  paddingLeft:12px;
`

/**
 *
 */
const LocationHeader = () => {

  const Navigation = useNavigation<ScreenNavigationProp>()
  const Location = useLocation()
  const locationSheetRef = useRef<BottomSheet>()

  const onSearch = () => {
    Navigation.navigate('Search')
  }

  const onLocation = () => {
    locationSheetRef.current?.open()
  }


  return <DropShadow intensity={0.1}>
    <Container>
      <LocationButton text={Location.label} left={Location.loading ? AnimatedSpinner : Icons.IconFilter} onPress={onLocation} />
      <LocationSheet ref={locationSheetRef} />
    </Container>
  </DropShadow>
}

/**
 * Module exports
 */
export {
  LocationHeader
};

下面的代码似乎有错误:超过了最大更新深度。当组件在useEffect中调用setState时,可能会发生这种情况,但useEfect要么没有依赖项数组,要么在每次渲染时都会更改其中一个依赖项。ForwardRef中(位于LocationHeader.tsx:62)

import React, { MutableRefObject, useRef, useEffect, useState } from 'react';
    import BottomSheet from 'react-native-raw-bottom-sheet';
    import styled, { css } from 'styled-components/native';
    import Icons from '../../assets/icons'
    import {
      TextBold, Text, ButtonWhite, Block, AsyncContent, ButtonClear, CenterFill, Row
    } from '../../components';
    import { Colors } from '../Theme';
    import { SearchField } from '../search/SearchHeader'
    import { useLocation } from '../../context/location';
    import { Place } from '../../models/Place';
    import { useApi, useUi } from '../../context';
    import { useAsync } from '../../hooks/useAsync';
    import { FlatList } from 'react-native';
    import { delay, isTruthy } from '../../utils/helpers';
    
    const SearchContainer = styled(Row)`
      
    `
    
    const ButtonLocation = styled(ButtonWhite)`
      color:${Colors.Orange};
      text-align:left;
    `
    
    const PoppinsBold14 = css`
      fontSize:14px;
    `
    
    
    const Heading = styled(TextBold)`
      padding:20px;
      color:${Colors.AlmostBlack};
      textAlign:center;
      ${PoppinsBold14};
    `
    
    
    const SearchBlock = styled.View`
      flex:1;
      padding: ${Block}px;
      padding-top: 0px;
    `
    
    const ErrorText = styled(Text)`
    margin-top:${Block * 2}px;
    color:${Colors.Grey};
      text-align:center;
    `
    
    const RegionsEmpty = () => {
    
      // return <TextBold text='No matches found' />
      return <CenterFill>
        <Icons.ImageNoResultsLocation width="150px" height="150px" />
        <ErrorText text={
          `Location not found
    Try a new search`
        } />
      </CenterFill>
    }
    
    const PlaceSeparator = styled.View`
      width:100%;
      height:1px;
      background-color:${Colors.GreyLight};
    `
    
    const PlaceButton = styled(ButtonClear)`
      text-align:left;
      font-family: Poppins-Regular;
      color: ${Colors.AlmostBlack};
    `
    
    const PlaceItem = (props: { place: Place, onClick: () => void }) => {
    
      return <PlaceButton text={props.place.name} onPress={props.onClick} left={Icons.IconSearchLocation} />
    }
    
    const LocationSheet = React.forwardRef((props, ref: React.MutableRefObject<BottomSheet>) => {
    
      const Location = useLocation()
      const Api = useApi()
      const Ui = useUi()
      const [query, setQuery] = useState('')
    
      const sheetRef: MutableRefObject<BottomSheet> = ref ?? useRef<BottomSheet>()
    
      const { value: suburbs, error, loading, execute: fetchRegions } = useAsync(async () => {
    
        // const regions = await Api.getRegions()

        const suburbs = await Api.getSuburbs('newyork')
    
        return suburbs
    
      }, false);
    
      useEffect(() => {
    
        if (!Location.isDeviceLocation) {
          fetchRegions()
        }
    
      }, [Location.isDeviceLocation])
    
      /**
       * 
       */
      const closeSheet = () => {
    
        sheetRef.current?.close()
    
        // Always reset search state on close so that list is reset on next open
        setQuery('')
      }
    
      /**
       * Handles user interaction with location toggle
       */
      const onClickLocationMode = async () => {
        try {
    
          if (await Location.toggleMode() === 'DeviceLocation') {
    
            // For user experience
            await delay(300)
    
            closeSheet()
          }
    
        }
        catch (error) {
          Ui.showErrorToast(error)
        }
      }
    
      /**
       * 
       * @param place 
       */
      const onClickPlace = (place: Place) => async () => {
    
        Location.setPlace(place)
    
        // For user experience
        await delay(300)
    
        closeSheet()
      }
    
      /**
       * 
       * @param place 
       */
      const isRegionKeywordMatch = (place: Place) => {
        return place.name.match(new RegExp(query, 'gi')) !== null
      }
    
      return <BottomSheet
        height={600}
        customStyles={{
          container: {
            borderTopLeftRadius: 10,
            borderTopRightRadius: 10
          }
        }}
        openDuration={500}
        ref={sheetRef}>
    
        <Heading text="Location settings" />
        <SearchBlock>
          <ButtonLocation text="Use current location" onPress={onClickLocationMode} left={Icons.IconSearchLocation} right={Location.isDeviceLocation ? Icons.Tick : null} />
          <SearchContainer>
            {/* TODO: Search container needed to keep field icon vertically centered */}
            <SearchField placeholder="Search for location" onChangeText={setQuery} left={Icons.IconSearch} />
          </SearchContainer>
          <AsyncContent loading={loading} error={error} value={suburbs} retry={fetchRegions} render={suburbs => {
    
            const suburbsFiltered = isTruthy(query) ?
              suburbs.filter(isRegionKeywordMatch) :
              suburbs
    
            const hasQuery = isTruthy(query)
    
            if (!hasQuery) {
              return null 
            }
            else {
              return <FlatList
                data={suburbsFiltered}
                ListEmptyComponent={RegionsEmpty}
                ItemSeparatorComponent={PlaceSeparator}
                keyExtractor={(region) => `${region.id}`}
                renderItem={({ item: suburb }) => <PlaceItem place={suburb} onClick={onClickPlace(suburb)} />}
              />
            }
          }} />
        </SearchBlock>
      </BottomSheet>
    })
    
    export {
      LocationSheet
    };

共有1个答案

柯立果
2023-03-14

如果Location.isDeviceLocation不断更新并因此每次都触发useEffect,就会发生这种情况。你能展示一下位置表的其余部分吗?

编辑:尝试将fetchRegions添加到依赖项数组中。

 useEffect(() => {
    
        if (!Location.isDeviceLocation) {
          fetchRegions()
        }
    
      }, [Location.isDeviceLocation, fetchRegions])
 类似资料:
  • 我正在用React做我的前几个实验,在这个组件中,我调用了一个外部API来获取所有NBA玩家的列表,通过作为组件道具接收的teamId过滤它们,最后呈现过滤玩家的标记。 一个需要考虑的问题是,由于我调用了API并获得了一个大列表,所以我将它保持在组件的状态,以便对该组件的新调用将使用该状态,而不是再次调用API。这不是生产代码,我没有API,所以我这样做是因为我收到了“太多请求”消息,因为我一直在

  • 当我运行我的代码时,我收到了这个错误。 超过了最大更新深度。当组件重复调用组件WillUpdate或组件DidUpdate中的setState时,可能会发生这种情况。React限制嵌套更新的数量以防止无限循环。 这是代码。它在引用。 我按照React网站上的文章所说的方式设置了我的东西,它“来了”于这个简洁的控制台类型,这就是我产生上述代码的地方。我对React、JSX和Javascript(以及

  • 我有这个错误:错误:超过最大更新深度。当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时,会发生这种情况。React限制嵌套更新的数量,以防止无限循环。 但是我不明白怎么解决!我只是在发布我的代码,对不起… 我的代码:

  • 早上好,我正在开发一个React应用程序,通过REST API与后端通信。 该应用程序体系结构还使用 React 路由器,并使用服务器提供并存储在中的 JWT 令牌实现身份验证功能。 基本上: 用户连接到应用程序 如果用户未登录,则重定向到登录页面 登录后,它会重定向到带有路径的主页,其中应该显示带有路径的组件和带有路径的组件(如果一个很好地理解React路由器的工作) 在启动应用程序时,用户被正

  • 我正在尝试使用master中的一些函数。js组件。当我运行下面的代码时,我得到错误“error:Maximum update depth exceeded。当组件在componentWillUpdate或componentDidUpdate.React中重复调用setState时,可能会发生这种情况。React限制嵌套更新的数量,以防出现无限循环。” 我在孙子组件中添加按钮时出错了。 如果我注释掉

  • 我正在使用FullCalendar进行反应,我正在与状态作斗争……它返回以下消息: 错误:超过最大更新深度。当组件在componentWillUpdate或componentDidUpdate内重复调用setState时,可能会发生这种情况。React限制嵌套更新的数量,以防止无限循环。 我删除了代码中所有不必要的部分。 如果您想让我提供更多信息,请告诉我。欢迎任何反馈/想法!谢谢