我目前收到“最大更新深度”错误,不确定为什么。在我的代码中看不到无限循环。
“超过了最大更新深度。当组件在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时会发生这种情况,但是useEffect要么没有依赖项数组,要么每个渲染上的依赖项之一发生更改。 在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
};
答案 0 :(得分:0)
如果Location.isDeviceLocation不断更新并因此每次触发useEffect,就会发生这种情况。您能否显示其余的LocationSheet组件?
编辑:尝试将fetchRegions添加到依赖项数组中。
useEffect(() => {
if (!Location.isDeviceLocation) {
fetchRegions()
}
}, [Location.isDeviceLocation, fetchRegions])