如何防止在React Class组件中重新呈现/获取数据?

时间:2020-02-20 23:42:02

标签: javascript reactjs react-native react-redux

我正在使用React Native在音乐应用程序中工作,在主屏幕中,我使一个类组件包含了四个以上的FlatList,并且它是从API中获取数据“它是大数据”,

因此我为此创建了一个函数,并将其放在componentDidMount()中,

但是我注意到,当我在setState之后记录数据时,在RN-Debugger中看到它两次以上

那么我该如何防止这种情况发生? 因为它会影响性能:)

这是我的代码段

class Home extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      url: '******',
      loading: false,
      minimal: false,
      MiniURL: '',
      songName: '',
      currentTrackIndex: 0,
      isPlaying: true,
    };
  }
  getRecentSongs = async () => {
    try {
      let response = await API.get('/index');
      let {recent_tracks} = response.data.data;
      let recent_tunes = [];
      recent_tracks.map(track =>
        recent_tunes.push({
          id: track.id,
          name: track.name,
          url: this.state.url + track.sounds,
          img: this.state.url + track.avatar,
        }),
      );
      let data = response.data.data;
      this.setState({data, recent_tunes, loading: true}, () =>
        console.log('data', this.state.data),
      );
    } catch (error) {
      console.log(error);
      this.setState({error: true});
    }
  };
  componentDidMount() {
    this.getRecentSongs();
  }



_renderItem = ({item, index}) => {
    const {url} = this.state;
    return (
      <TouchableNativeFeed
        key={item.id}
        onPress={() => {
          this.props.navigation.navigate({
            key: 'Player',
            routeName: 'Player',
            params: {
              tunes: this.state.recent_tunes,
              currentTrackIndex: index,
            },
          });
        }}
        background={TouchableNativeFeedback.Ripple('white')}
        delayPressIn={0}
        useForeground>
        <Card style={styles.card} noShadow={true}>
          <FastImage
            style={{width: 200, height: 200}}
            source={{uri: url + item.avatar}}
            resizeMode={FastImage.resizeMode.cover}
            style={styles.cardImg}
          />
          <Body style={styles.cardItem}>
            <View style={styles.radioCardName}>
              <View style={styles.cardViewFlex}>
                <Text style={styles.text}>{item.name}</Text>
              </View>
            </View>
          </Body>
        </Card>
      </TouchableNativeFeed>
    );
  };

render(){
  const {data} = this.state;

   return(
        ...
        {/* Recent Songs Here*/}
            <View style={{marginVertical: 10}}>
              <FlatList
                horizontal={true}
                showsHorizontalScrollIndicator={false}
                data={data.recent_tracks}
                contentContainerStyle={{flexGrow: 1}}
                ListEmptyComponent={<EmptyList />}
                keyExtractor={(track, index) => track.id.toString()}
                // initialNumToRender={10}
                renderItem={this._renderItem}
              />
            </View>
     ...
  )
 }

}

3 个答案:

答案 0 :(得分:0)

很难从发布的内容中看出来,但是其中一个组件的键是否可能比您期望的更频繁地更改?如果检测到任何关键更改,React将触发完全重新渲染。

答案 1 :(得分:0)

ComponentDidMount将仅执行一次,并在删除后卸载。因此,这意味着它在应用程序的某些部分被创建了两次。

我遇到了类似的问题,并且与我的导航库有关,就我而言,我使用的是反应导航https://github.com/react-navigation/react-navigation/issues/2599

因此,我建议您检查创建组件时是否发生了某些事情,以及是否执行了两次。另外,请仔细检查您的导航是否执行相同的操作。

答案 2 :(得分:0)

请使用React.memo

在道具中没有任何相关数据的情况下,它将不会重新渲染组件。

例如:

/**Your render item*/

const AddsItem = React.memo(({item, index}) => {
   return (
      <TouchableNativeFeed
...
...
</TouchableNativeFeed>
    );
});


/**Your class*/
class Home extends React.Component {
  constructor(props) {
...
}

render(){
  const {data} = this.state;

   return(
...
...
...
)
}