我正在使用Hooks和ES6构建一个React Native应用。
主屏幕从API提取一些数据并将其显示为图像库。 主屏幕是父组件,其中包括幻灯片库和子目录。
1)幻灯片放映-图像库自动播放,在每次图像迭代(每3秒)上运行一些操作(以防用户点击时获取URL)-这会导致整个父组件及其子组件的重新渲染,但是按预期每3秒渲染一次
2)平面列表-只是一个简单的平面列表,需要一个图像数组-当首先加载父组件时,该应该只渲染一次
问题
每3秒钟在幻灯片放映中显示一个新图像,运行一个函数为显示的图像获取一些道具,重新渲染父组件,但是由于第二个图库中的Flatlist不需要再次运行,图片数组与最初加载的图片相同(不变)
这是我的父母密码
const getTopTenMovies = (state) => state.moviescreen.popularmovies //fetching data from Redux
const upcomingMovies = (state) => state.moviescreen.upcomingmovies
const MoviesScreen = (props) => {
const topTenMovies = useSelector(getTopTenMovies);
const [imageIndex, setImageIndex] = useState("");
/* useEffect below runs every time imageIndex changes (a new image is displayed every 3 secs) */
useEffect(() => {
setCarouselMovieId(selectedImageItem.id);
setCarouselMovieTitle(selectedImageItem.title);
}, [imageIndex]);
/* user clicks on an image and is taken to another screen
const fetchMovieHandler = async (movieId, movieTitle) => {
props.navigation.navigate({
routeName: "MovieDetail",
params: {
assetId: movieId,
assetName: movieTitle,
},
});
};
return (
<ImageGallery
data={topTenMovies}
currentImage=setImageIndex(index)
...
/>
<View style={styles.containerRow}>
<FlatList
horizontal={true}
data={upcomingMovies}
initialNumToRender={5}
windowSize={10}
removeClippedSubviews={true}
keyExtractor={(item) => item.id.toString()}
renderItem={(itemData) => (
<HomeItem
id={itemData.item.id}
poster={itemData.item.poster_path}
onAssetSelection={fetchMovieHandler}
/>
)}
/>
</View>
</View>
)
}
该组件在Flatlist中呈现单个图像,并将参数(movieId,movieTitle)传递给fetchMovieHandler函数。
下面的HomeItem代码...
class HomeItem extends React.PureComponent {
render() {
const assetHandler = async () => {
this.props.onAssetSelection(this.props.id, this.props.title);
};
console.log("HomeItem is called");
return (
<TouchableOpacity onPress={assetHandler}>
<View>
<Image
key={this.props.id}
source={{
uri: `https://*******${this.props.poster}`,
}}
/>
</View>
</TouchableOpacity>
);
}
}
export default React.memo(HomeItem);
每隔3秒就会调用一次HomeItem,我会看到10条日志条目(每个图像和渲染一个)-即将上映的电影有10张图像。从UI来看一切正常,因为图像似乎没有变化,可能是因为我已将HomeItem定义为PureComponent并使用React.memo(HomeItem),但是由于出现以下错误,这会导致性能问题:
VirtualizedList:您的列表很大,更新速度很慢-确保您的renderItem函数呈现遵循React性能最佳实践的组件,例如PureComponent,shouldComponentUpdate等
我试图将Flatlist包含在HomeItem组件中,但问题仍然存在。
答案 0 :(得分:1)
经过进一步的研究,并感谢@landorid的建议,我发现我需要控制FlatList的renderItem,方法是在具有useCallback钩子并依赖于我的数据源的单独函数中声明它。
试图将Flatlist包含在单独的PureComponent中,但重新渲染一直在发生。
理想的解决方案是更改此代码
renderItem={(itemData) => (
<HomeItem
id={itemData.item.id}
poster={itemData.item.poster_path}
onAssetSelection={fetchMovieHandler}
/>
)}
像这样
.....
const renderRow = ({ itemData }) => {
return (
<HomeItem
id={itemData.item.id}
poster={itemData.item.poster_path}
title={itemData.item.title}
onAssetSelection={fetchMovieHandler}
/>
);
};
keyExtractor = (item) => item.id.toString();
return (
<FlatList
horizontal={true}
data={upcomingMovies}
initialNumToRender={5}
windowSize={10}
removeClippedSubviews={true}
keyExtractor={keyExtractor}
renderItem={renderRow}
/>
,然后将renderRow()函数包装在useCallback挂钩中。
问题在于我的数据源data = {upcomingMovies}是具有2个级别的对象的数组,例如,我需要使用itemData.item.title来检索标题值。
虽然它可以在我当前的renderItem设置中工作,但是当我在
的外部函数中使用它时将无法工作 const renderRow = ({ itemData }) => {
return (
<HomeItem
id={itemData.item.id}
poster={itemData.item.poster_path}
title={itemData.item.title}
onAssetSelection={fetchMovieHandler}
/>
);
};
我只是得到“ item”变量不可用
关于如何修改功能的任何建议?
答案 1 :(得分:0)
如果我是你,我将更改以下内容:
Component
扩展名而不是PureComponent
,并将您的道具与`shouldComponentUpdate比较。 (我认为传递的函数onAssetSelection导致重新渲染。检查它。)React.memo
,因为它用于功能组件。