我的react本机应用程序中的组件之一正在重新渲染多次,导致派生数据出现问题。我正在使用Redux存储状态,并使用useSelector钩子检索状态并在渲染期间使用它。我已经阅读了很多有关使用Reselect库的信息,以避免不必要的渲染和优化性能,但是我正努力通过钩子将其应用于ES6代码。
这是我当前的代码
import { useSelector, useDispatch } from "react-redux";
import...
const MovieDetailScreen = (props) => {
const selectedMovie = useSelector((state) => state.moviemain.moviemain);
const selectedMovieCast = useSelector((state) => state.moviecast.moviecast);
const selectedMovieCrew = useSelector((state) => state.moviecast.moviecrew);
return (
<View style={styles.container}>
<View>
<Text style={styles.description} numberOfLines={3}>
{selectedMovie.name}
</Text>
</View>
<View>
<Text style={styles.description} numberOfLines={3}>
{selectedMovie.overview}
</Text>
</View>
<View>
<Text style={styles.description} numberOfLines={3}>
{selectedMovie.released_date}
</Text>
</View>
<View style={styles.textLabelRow}>
{selectedMovie.genres.map((item, id) => {
return (
<Text
style={[styles.txtLabel, { backgroundColor: "#404040" }]}
key={id}
numberOfLines={1}
>
{item.name}
</Text>
);
})}
</View>
</View>
...
...
);
};
我想将Reselect应用于任何派生数据,在附带的示例代码中,它将是selectedMovie状态的genres参数的映射处理
{selectedMovie.genres.map((item, id) => {
return (
<Text
style={[styles.txtLabel, { backgroundColor: "#404040" }]}
key={id}
numberOfLines={1}
>
{item.name}
</Text>
);
})}
我还有另外数十种类似的情况,需要过滤数据或计算总数,由于重新渲染,我经常会出错。我相信使用Reselect,该功能仅在状态更改时才能执行。
我试图通过将状态选择移到组件之外并像这样重组代码来遵循here中的示例
import...
import { createSelector } from "reselect";
const getMovie = createSelector(
(state) => state.moviemain.moviemain,
(moviemain) => moviemain.moviemain.map((item) => item.genres)
);
export const GenresList = () => {
const genres = useSelector(getMovie);
return (
<Text
style={[styles.txtLabel, { backgroundColor: "#404040" }]}
numberOfLines={1}
>
{genres}
</Text>
);
};
const MovieDetailScreen = (props) => {
const selectedMovie = useSelector((state) => state.moviemain.moviemain);
const selectedMovieCast = useSelector((state) => state.moviecast.moviecast);
const selectedMovieCrew = useSelector((state) => state.moviecast.moviecrew);
return (
<View style={styles.container}>
....
....
<View>
<GenresList />
</View>
</View>
...
...
);
};
但是我在createSelector函数中遇到以下错误未定义不是对象(正在评估'moviemain.moviemain.map')
我已经尝试了其他建议的解决方案,这些解决方案在主要组件中包含所有代码,但是我遇到其他类型的错误。
我希望获得一些指导。
TLDR;在下面的代码中,第一个参数返回moviemian.moviemain属性,而下一行则要获取该行的moviemain属性-含义:moviemian.moviemain.moviemain尚未定义,因此您无法映射它。
const getMovie = createSelector(
(state) => state.moviemain.moviemain,
(moviemain) => moviemain.moviemain.map((item) => item.genres)
);
记住:在选择器中编写的内容将在第二个参数中得到结果。
解决方案:删除多余的电影main:
(moviemain) => moviemain.map((item) => item.genres)
Redux选择器可能很棘手,这是一个复习
// you can either use multiple selectors
// declare these outside of component
const getSelectedMovie = (state) => state.moviemain.moviemain;
const getSelectedMovieCast = (state) => state.moviecast.moviecast;
const getSelectedMovieCrew = (state) => state.moviecast.moviecrew;
// or use one since its the same object
const getSelectedMovieAll = (state) => state.moviemain;
// so that you can use them inside component like
const MovieDetailScreen = (props) => {
const selectedMovie = useSelector(getSelectedMovie);
const movies = useSelector(getSelectedMovieAll);
// pay attention to the keys, they remain the same
const { moviecast: selectedMovieCast, moviecrew: selectedMovieCrew } = movies;
}
嗯,这是关于redux的部分,关于重新选择,您可以像这样使用它:
const example = createSelector(
[selector1, selector2]
(resultOfSelector1, resultOfSelector2) => ({ 'return': 'something'})
);
// so in case moviemain.moviemain is an array you can do the following
// make sure you reuse the previous selectors
const getMovie = createSelector(
[getSelectedMovie]
(moviemain) => moviemain.map((item) => item.genres)
);
export const GenresList = () => {
const genres = useSelector(getMovie);
return (