在React Native中使用带有Hooks的备注选择器

问题描述 投票:0回答:1

我的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')

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

我希望获得一些指导。

react-native react-redux memoization reselect redux-react-hook
1个回答
0
投票

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

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 (
© www.soinside.com 2019 - 2024. All rights reserved.