在React Native中将备注选择器与挂钩一起使用

时间:2020-05-12 13:00:47

标签: react-native react-redux memoization reselect redux-react-hook

我的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.movi​​emain.map”)

我尝试了其他建议的解决方案,这些解决方案在主要组件中包含所有代码,但是我遇到其他类型的错误。

我希望您能提供一些指导。

1 个答案:

答案 0 :(得分:0)

TLDR ; 在下面的代码中,第一个参数返回moviemian.movi​​emain属性,而下一行要获取该属性的moviemain属性-意思是:moviemian.movi​​emain.movi​​emain,它是未定义的,因此您无法映射它。

plt.gca().set_color_cycle(['green', 'yellow'])
for dtype in ['Y', 'N']:
  plt.plot(
     'Datetime',
     dtype,
     data=df,
     label=dtype,
     alpha=0.8
     )
plt.legend()
plt.grid() 
plt.show() 

记住:在选择器中编写的内容将在第二个参数中得到结果。

解决方案:删除多余的电影main:

const getMovie = createSelector(
  (state) => state.moviemain.moviemain,
  (moviemain) => moviemain.moviemain.map((item) => item.genres)
);

Redux选择器可能很棘手,这是一个复习

(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;

}