Reactjs 提高在React中渲染数百个组件的性能

Reactjs 提高在React中渲染数百个组件的性能,reactjs,react-native,Reactjs,React Native,我正在React Native中呈现一个列表,它当前有大约900个列表项。我正在映射列表,并为每个项目呈现一个组件。它目前需要约3秒的反应来做这是不可接受的-我希望它是近瞬间。道具从redux存储区传递到列表项组件,列表项嵌套在React NativeScrollView组件中 我如何才能提高渲染这些组件的性能,从而避免出现如此大的延迟 这是我的联系人组件: class Contacts extends Component { renderRegisteredUsers = (conta

我正在React Native中呈现一个列表,它当前有大约900个列表项。我正在映射列表,并为每个项目呈现一个组件。它目前需要约3秒的反应来做这是不可接受的-我希望它是近瞬间。道具从redux存储区传递到列表项组件,列表项嵌套在React Native
ScrollView
组件中

我如何才能提高渲染这些组件的性能,从而避免出现如此大的延迟

这是我的
联系人
组件:

 class Contacts extends Component {

  renderRegisteredUsers = (contacts) => {
    return contacts.items.map((contact, index) => (
      <ContactListItem
        key={index}
        firstName={contact.user.address_book_name}
        surname={''}
        phoneNumber={contact.user.phone}
        isRegisteredUser={true}
        ccId={contact.user.id}
      />
    ))
  }

  renderContacts = (contacts) => {
    if (contacts) {
      return contacts.map((contact, index) => (
        <ContactListItem
          key={index}
          firstName={contact.firstName}
          surname={contact.surname}
          phoneNumber={contact.phoneNumber}
          isRegisteredUser={false}
        />
      ))
    } else {
      return (
        <>
          <Loader />
        </>
      )
    }
  }

  render() {
    return (
      <>
        <ScrollView>
          <Text style={{ fontSize: 22 }}>
            Your Contacts Using Fleeting
        </Text>
          {this.renderRegisteredUsers(this.props.user.registeredContacts)}
          <Text style={{ fontSize: 22 }}>
            Phone Contacts
        </Text>
          {this.renderContacts(this.props.user.parsedContacts)}
        </ScrollView>
      </>
    )
  }
}

const mapStateToProps = (state) => {
  const { user } = state;
  return { user }
};

export default connect(mapStateToProps)(Contacts);

class ContactListItem extends Component {
  constructor(props) {
    super(props)
  }

  handleOnClick = () => {
    this.props.calleeId(this.props.ccId)
    Actions.TimeInput();
  }

  render() {
    return (
      <View style={{ margin: 20, display: "flex", flexDirection: "column", justifyContent: "space-between" }}>
        <Text>
          {this.props.firstName + ' ' + this.props.surname + '                          ' + this.props.phoneNumber}
        </Text>
        <Icon name="adduser" size={40} color="green" style={{ alignSelf: "flex-end" }} onPress={this.handleOnClick} />
      </View>
    )
  }
}

const mapDispatchToProps = {
  calleeId,
};

export default connect(null, mapDispatchToProps)(ContactListItem);

提前感谢。

请考虑改用分页-。如果您的联系人来自api请求,您也必须考虑对请求进行分页


import React, { Component } from 'react';
import {AppRegistry,StyleSheet,View,FlatList,} from 'react-native';
import ContactItem from './Pages/widgets/ContactItem'; // https://github.com/garrettmac/react-native-pagination/blob/master/ReactNativePaginationExample/Pages/widgets/ContactItem.js
import faker from 'faker';//assuming you have this.
import _ from 'lodash';
import Pagination,{Icon,Dot} from 'react-native-pagination';//{Icon,Dot} also available



export default class ReactNativePaginationExample extends Component {
  constructor(props){
     super(props);
      this.state = {
        items: this.props.contacts,
      };
    }
    //create each list item
  _renderItem = ({item}) => {
    return (<ContactItem index={item.id}
        onPressItem={this.onPressItem.bind(this)}
        name={item.name}
        avatar={item.avatar}
        description={item.email}
        tag={item.group}
        createTagColor
      />)
    };
    //pressed an item
  onPressItem = (item) => console.log("onPressItem:item ",item);


  _keyExtractor = (item, index) => item.id;

  onViewableItemsChanged = ({ viewableItems, changed }) =>this.setState({viewableItems})

  render() {
    return (
      <View style={[s.container]}>
          <FlatList
            data={this.state.items}
            ref={r=>this.refs=r}//create refrence point to enable scrolling
            keyExtractor={this._keyExtractor}//map your keys to whatever unique ids the have (mine is a "id" prop)
            renderItem={this._renderItem}//render each item
            onViewableItemsChanged={this.onViewableItemsChanged.bind(this)}//need this
          />

          <Pagination
            // dotThemeLight //<--use with backgroundColor:"grey"
            listRef={this.refs}//to allow React Native Pagination to scroll to item when clicked  (so add "ref={r=>this.refs=r}" to your list)
            paginationVisibleItems={this.state.viewableItems}//needs to track what the user sees
            paginationItems={this.state.items}//pass the same list as data
            paginationItemPadSize={3} //num of items to pad above and below your visable items
          />
        </View>
      )
  }
};

const s = StyleSheet.create({
  container: {
    flex: 1,
    // backgroundColor:"grey",//<-- use with "dotThemeLight"
  },
});

AppRegistry.registerComponent('ReactNativePaginationExample', () => App);



从“React”导入React,{Component};
从“react native”导入{AppRegistry、样式表、视图、平面列表,};
从“./Pages/widgets/ContactItem”导入ContactItem;//https://github.com/garrettmac/react-native-pagination/blob/master/ReactNativePaginationExample/Pages/widgets/ContactItem.js
从“冒牌货”进口冒牌货//假设你有这个。
从“lodash”进口;
从'react native Pagination'导入分页,{Icon,Dot}//{图标,点}也可用
导出默认类ReactNativePaginationExample扩展组件{
建造师(道具){
超级(道具);
此.state={
项目:this.props.contacts,
};
}
//创建每个列表项
_renderItem=({item})=>{
返回()
};
//按一项
onPressItem=(item)=>console.log(“onPressItem:item”,item);
_keyExtractor=(项,索引)=>item.id;
onViewableItemsChanged=({viewableItems,changed})=>this.setState({viewableItems})
render(){
返回(
this.refs=r}//创建引用点以启用滚动
keyExtractor={this.\u keyExtractor}//将您的密钥映射到具有的唯一id(我的是“id”属性)
renderItem={this.\u renderItem}//呈现每个项目
onViewableItemsChanged={this.onViewableItemsChanged.bind(this)}//需要这个吗
/>
)
}
};
const s=StyleSheet.create({
容器:{
弹性:1,
//背景颜色:“灰色”,//应用程序);

改为使用分页。如果您的联系人来自api请求,您也必须考虑对请求进行分页


import React, { Component } from 'react';
import {AppRegistry,StyleSheet,View,FlatList,} from 'react-native';
import ContactItem from './Pages/widgets/ContactItem'; // https://github.com/garrettmac/react-native-pagination/blob/master/ReactNativePaginationExample/Pages/widgets/ContactItem.js
import faker from 'faker';//assuming you have this.
import _ from 'lodash';
import Pagination,{Icon,Dot} from 'react-native-pagination';//{Icon,Dot} also available



export default class ReactNativePaginationExample extends Component {
  constructor(props){
     super(props);
      this.state = {
        items: this.props.contacts,
      };
    }
    //create each list item
  _renderItem = ({item}) => {
    return (<ContactItem index={item.id}
        onPressItem={this.onPressItem.bind(this)}
        name={item.name}
        avatar={item.avatar}
        description={item.email}
        tag={item.group}
        createTagColor
      />)
    };
    //pressed an item
  onPressItem = (item) => console.log("onPressItem:item ",item);


  _keyExtractor = (item, index) => item.id;

  onViewableItemsChanged = ({ viewableItems, changed }) =>this.setState({viewableItems})

  render() {
    return (
      <View style={[s.container]}>
          <FlatList
            data={this.state.items}
            ref={r=>this.refs=r}//create refrence point to enable scrolling
            keyExtractor={this._keyExtractor}//map your keys to whatever unique ids the have (mine is a "id" prop)
            renderItem={this._renderItem}//render each item
            onViewableItemsChanged={this.onViewableItemsChanged.bind(this)}//need this
          />

          <Pagination
            // dotThemeLight //<--use with backgroundColor:"grey"
            listRef={this.refs}//to allow React Native Pagination to scroll to item when clicked  (so add "ref={r=>this.refs=r}" to your list)
            paginationVisibleItems={this.state.viewableItems}//needs to track what the user sees
            paginationItems={this.state.items}//pass the same list as data
            paginationItemPadSize={3} //num of items to pad above and below your visable items
          />
        </View>
      )
  }
};

const s = StyleSheet.create({
  container: {
    flex: 1,
    // backgroundColor:"grey",//<-- use with "dotThemeLight"
  },
});

AppRegistry.registerComponent('ReactNativePaginationExample', () => App);



从“React”导入React,{Component};
从“react native”导入{AppRegistry、样式表、视图、平面列表,};
从“./Pages/widgets/ContactItem”导入ContactItem;//https://github.com/garrettmac/react-native-pagination/blob/master/ReactNativePaginationExample/Pages/widgets/ContactItem.js
从“faker”导入faker;//假设您有这个。
从“lodash”进口;
从“反应本机分页”导入分页,{Icon,Dot};//{Icon,Dot}也可用
导出默认类ReactNativePaginationExample扩展组件{
建造师(道具){
超级(道具);
此.state={
项目:this.props.contacts,
};
}
//创建每个列表项
_renderItem=({item})=>{
返回()
};
//按一项
onPressItem=(item)=>console.log(“onPressItem:item”,item);
_keyExtractor=(项,索引)=>item.id;
onViewableItemsChanged=({viewableItems,changed})=>this.setState({viewableItems})
render(){
返回(
this.refs=r}//创建引用点以启用滚动
keyExtractor={this.\u keyExtractor}//将您的密钥映射到具有的唯一id(我的是“id”属性)
renderItem={this.\u renderItem}//呈现每个项目
onViewableItemsChanged={this.onViewableItemsChanged.bind(this)}//需要这个吗
/>
)
}
};
const s=StyleSheet.create({
容器:{
弹性:1,
//背景颜色:“灰色”,//应用程序);

1-您可以使用
PureComponent
而不是
Component
。PureComponent仅在其道具更改时重新渲染,而不是在每个父级重新渲染时重新渲染。详细信息:

2-在映射项目时使用唯一的
s

3-您可以使用
FlatList
而不是
ScrollView
。它支持
滚动加载
。您可以设置一些初始数字,并在滚动中呈现其他数字。详细信息:

constrenderitem=({item})=>({item.key});
const getItemLayout=(数据、索引)=>(
{长度:项目高度,偏移量:项目高度*索引,索引}
);
常量项=[{key:'first'},{key:'second'},…+1000];
函数render()=>(
);

1-您可以使用
PureComponent
而不是
Component
。PureComponent仅在其道具更改时重新渲染,而不是在每个父级重新渲染时重新渲染。详细信息:

2-在映射项目时使用唯一的
s

3-您可以使用
FlatList
而不是
ScrollView
。它支持
滚动加载
。您可以设置一些初始数字,并在滚动中呈现其他数字。详细信息:

constrenderitem=({item})=>({item.key});
const getItemLayout=(数据、索引)=>(
{长度:项目高度,偏移量:项目高度*索引,索引}
);
常量项=[{key:'first'},{key:'second'},…+1000];
函数render()=>(
);

分页是正确答案,但实际上应该包括一个简短的代码示例。分页是正确答案,但实际上应该包括一个简短的代码示例。