我正在尝试提高应用程序的性能,因此我使用FC渲染项目,
但是对我来说效果不佳!
当我向下滚动到++页面时
并在useEffect()中,我发送请求以根据页面的工作获取新数据,并在UI中很好地渲染项目! “加载更多功能”。
但是,当我在单击项目之前记录“歌曲”整个数组时,我只会得到前两页!有时我会得到一个空数组。
那我的代码有什么问题吗?
const LastSongs = (props) => {
const [songs, setSongs] = React.useState([]);
const [loading, setLoading] = React.useState(false);
const [page, setPage] = React.useState(1);
const [last_page, setLast_page] = React.useState(1);
const {saveSongs, isPlaying, isPauseTrigger} = props;
const _renderItems = useCallback(
// the same reference with each rerender
({item, index}) => (
<TouchableNativeFeed
key={item.id}
onPress={() => {
console.log('onPress', songs);
saveSongs(songs, index);
isPlaying(true);
isPauseTrigger(!isPauseTrigger);
}}
background={TouchableNativeFeedback.Ripple('white')}
delayPressIn={0}
useForeground>
<Card
style={{
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#121212',
flex: 1,
}}>
<FastImage
source={{uri: item.img}}
resizeMode={FastImage.resizeMode.cover}
style={styles.cardImg}
/>
<Body style={{...styles.cardItem, width: '100%'}}>
<View style={styles.radioCardName}>
<Text style={styles.text} numberOfLines={1}>
{item.name}
</Text>
</View>
</Body>
</Card>
</TouchableNativeFeed>
),
[saveSongs, isPlaying, isPauseTrigger],
);
const renderFooter = useCallback(
// the same reference with each rerender
() => {
return loading ? (
<View style={styles.loader}>
<ActivityIndicator size="large" />
</View>
) : null;
},
[loading],
);
const handleLoadMore = useCallback(
// the same reference with each rerender
() => {
if (page <= last_page - 1) {
setPage(page + 1);
}
},
[page, last_page],
);
React.useEffect(() => {
let isCancelled = false;
setLoading(true);
const getData = async () => {
let response = await API.get(`/tracks?page=${page}`);
let lastPage = response.data.data.items.last_page;
setLast_page(lastPage);
let {
data: {
data: {
items: {data},
},
},
} = response;
let All_Songs = [];
data.map((track) =>
All_Songs.push({
id: track.id,
name: track.name,
url: URL + track.sounds,
img: URL + track.avatar,
}),
);
setSongs(songs.concat(All_Songs));
setLoading(false);
};
getData();
console.log('songs', songs);
}, [page]);
return (
<Container style={styles.container}>
<Header
style={styles.darkHeader}
androidStatusBarColor="#121212"
iosBarStyle="light-content">
<Left>
<Button transparent onPress={() => props.navigation.goBack()}>
<Icon name="ios-arrow-forward" style={styles.colorWhite} />
</Button>
</Left>
<Body>
<Title style={styles.headerText}>last songs</Title>
</Body>
<Right></Right>
</Header>
<FlatList
data={songs}
keyExtractor={_keyExtractor} // the same reference with each rerender
initialNumToRender={10}
contentContainerStyle={styles.contentContainerStyle} // the same reference with each rerender
columnWrapperStyle={styles.columnWrapperStyle} // the same reference with each rerender
numColumns={2}
ListEmptyComponent={_renderListEmptyComponent} // the same reference with each rerender
renderItem={_renderItems}
onEndReached={handleLoadMore}
onEndReachedThreshold={100}
ListFooterComponent={renderFooter}
removeClippedSubviews={true}
maxToRenderPerBatch={1} // Reduce number in each render batch
maxToRenderPerBatch={100} // Increase time between renders
windowSize={7}
/>
</Container>
);
};
const _keyExtractor = (song) => song.id;
const _renderListEmptyComponent = () => <EmptyList />;
const mapDispatchToProps = (dispatch) => {
return {
isPlaying: (_isPlaying) => {
dispatch(isPlayingAction(_isPlaying));
},
isPauseTrigger: (_isPause) => {
dispatch(isPauseAction(_isPause));
},
saveSongs: (songs, index) => {
dispatch(saveSongsPlayer(songs, index));
},
};
};
export default connect(null, mapDispatchToProps)(LastSongs);
答案 0 :(得分:0)
尝试更改_renderItems上的依赖项数组以包含歌曲。更改为:
[saveSongs, isPlaying, isPauseTrigger, songs]
。这样,callBack的关闭将始终包含最新歌曲。
我强烈建议您使用react-hooks eslint选项。它们将极大地帮助您确保您不会在依赖项数组中丢失任何内容。 https://www.npmjs.com/package/eslint-plugin-react-hooks
如果在将歌曲添加到列表的依赖项数组之后,只有一个问题,则可以尝试:
const songsRef = useRef(songs);
useEffect(() => {
songsRef.current = songs;
}, [songs]);
然后使用songsRef.current代替_renderItems函数中的歌曲
从聊天更新:
好的,修复了无限循环:expo snack
之所以出现无限循环,是因为在useEffect的依赖项数组中有歌曲。这意味着每次将useEffect附加到歌曲数组时,useEffect都会重新触发。
我通过从数组中删除歌曲然后使用useState的回调方法来设置状态来修复它:setSongs(songs => songs.concat(all_songs));