首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >反应为什么我仍然使用react.memo,它的再现器?

反应为什么我仍然使用react.memo,它的再现器?
EN

Stack Overflow用户
提问于 2021-11-02 21:14:13
回答 1查看 104关注 0票数 1

我有一个列表与回收列表视图,在那里你可以点击一个项目,然后一个模式是打开的,在模式是与扁平列表的项目。所以如果我打开模式,它会重现2-3倍。如果我再次滚动或单击它的重现程序。但是为什么呢?我使用react.memo

回收器列表视图

代码语言:javascript
复制
import * as React from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Image, Dimensions } from 'react-native';
import { RecyclerListView, LayoutProvider, DataProvider } from 'recyclerlistview';
import I18n from 'i18n-js';
import { Feather } from '@expo/vector-icons';
import { Portal } from 'react-native-portalize';
import { ModalUppinfo } from '../../modal/uppinfo/modalUppinfo';
import { ModalDrops } from '../../modal/drops/modalDrops';
import { map1boss, map2boss, otherboss } from '../../../utils/mockData';

const { width, height } = Dimensions.get('window');

const Bosses = ({ data }) => {
  const modals = Array.from({ length: 8 }).map(_ => React.useRef(null).current);

  const [uppRef, setUppRef] = React.useState([]);
  const [dropRef, setDropRef] = React.useState([]);

  const openModalDrop = React.useCallback((dropdata) => {
    setDropRef(dropdata);
    modals[3].open();
  }, [modals]);

  const provider = React.useMemo(() => {
    return new DataProvider(
      (r1, r2) => {
        return r1 !== r2;
      }, index => {
        return 'index: ' + index;
      }
    )
  }, []);

  const dataProvider = React.useMemo(() => {
    return provider.cloneWithRows((data === 1) ? map1boss : (data === 2) ? map2boss : otherboss);
  }, [provider, map1boss, map2boss, otherboss]);

  const layoutProvider = new LayoutProvider((i) => {
    return dataProvider.getDataForIndex(i).type;
  }, (type, dim) => {
    switch(type) {
      case 'NORMAL':
        dim.height = 250;
        dim.width = width * 0.9;
      break;
      default:
        dim.height = 0;
        dim.width = 0;
      break;
    }
  });

  const Item = React.memo(({ name, image, level, translateID, upp, sell_price, dropinfo }) => (
    <View style={styles.item}>
      <Text style={styles.name}>{I18n.t(translateID)}</Text>
      <View style={{justifyContent: 'center', alignItems: 'center'}}>
        <Image source={image} resizeMode="contain" style={{height: 100, width: 100, marginBottom: 16 }} />
      </View>
      <View style={styles.itemFooter}>
        <TouchableOpacity onPress={() => openModalUpp(upp)} style={styles.infoBtn}>
          <Feather name="info" size={24} color="#333" />
          <Text>Uppinfo</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={() => openModalDrop(dropinfo)} style={styles.infoBtn}>
          <Feather name="info" size={24} color="#333" />
          <Text>Dropinfo</Text>
        </TouchableOpacity>
      </View>
    </View>
  ));

  const rowRenderer = (type, data) => {
    const { name, image, level, translateID, upp, sell_price, dropinfo } = data.item;
    return (
      <Item name={name} image={image} level={level} translateID={translateID} upp={upp} sell_price={sell_price} dropinfo={dropinfo} />
    )
  };

  return (
    <View style={styles.container}>
      <RecyclerListView 
        dataProvider={dataProvider}
        layoutProvider={layoutProvider}
        rowRenderer={rowRenderer}
        scrollViewProps={{showsVerticalScrollIndicator: false}}
        style={{flex: 1, marginTop: 20}}
      />
      <Portal>

        <ModalDrops DropInfo={dropRef} ref={el => (modals[3] = el)} />
      </Portal>
    </View>
  )
};

模态平面列表:

代码语言:javascript
复制
import * as React from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Image, Dimensions } from 'react-native';
import { Modalize } from 'react-native-modalize';
import faker from 'faker';

const { width } = Dimensions.get('window');

export const ModalDrops = React.forwardRef(({ DropInfo }, ref) => {
  console.log('Drops')
  const Item = React.memo(({ name, image, index }) => {
    console.log('rerender');
    return (
      <View style={styles.item}>
        <TouchableOpacity style={{justifyContent: 'center', alignItems: 'center', paddingRight: DropInfo.monster.length -1 === index ? 36 : 0}}>
          <Image source={{uri: faker.image.avatar()}} resizeMode="contain" style={{height: 80, width: 80, borderRadius: 8, marginBottom: 10}} />
        </TouchableOpacity>
      </View>
    )
  });

  function renderItem({ item, index }) {
    return <Item name={item.name} image={item.image} index={index} />
  };

  function key() {
    return Math.random(10000).toString();
  }
  return (
    <Modalize
      ref={ref}
      modalHeight={300}
      flatListProps={{
        data: DropInfo.monster,
        style: {
          padding: 8,
          flex: 1
        },
        renderItem: renderItem,
        horizontal: true,
        ListEmptyComponent: () => {
          return (
            <View style={styles.itemEmpty}>
              <Text>Nicht Droppbar</Text>
            </View>
          )
        },
        keyExtractor: key,
        showsHorizontalScrollIndicator: false,
        scrollEventThrottle: 16,
        contentContainerStyle: {
          justifyContent: 'center',
          alignItems: 'center'
        }
      }}
    />
  )
});

视频:https://gyazo.com/ff91667f7f0258320317aa7645a046cf ....................................................................................................................

EN

回答 1

Stack Overflow用户

发布于 2021-11-02 22:40:38

问题

在我看来,声明Item组件的方式有一个主要问题,它是在另一个组件内部声明的,因此在任何时候外部组件呈现时,它都会重新声明。这有效地卸载了以前的“实例”,并挂载了一个新的“实例”。从技术上讲,它不是重新渲染,它只是完全重新挂载。

解决方案

不要在其他React组件中声明React组件。在这样做的时候,和试图记录任何渲染结果都不会起作用,因为每个渲染周期都会创建并挂载一个新组件。将Item声明移到组件之外。

老板们

代码语言:javascript
复制
const Item = React.memo(({ .... }) => (
  <View style={styles.item}>
    ...
    </View>
  </View>
));

const Bosses = ({ data }) => {
  ...

  const rowRenderer = (type, data) => {
    const { name, image, level, translateID, upp, sell_price, dropinfo } = data.item;
    return (
      <Item
        name={name}
        image={image}
        level={level}
        translateID={translateID}
        upp={upp}
        sell_price={sell_price}
        dropinfo={dropinfo}
      />
    )
  };

  return (
    <View style={styles.container}>
      <RecyclerListView 
        dataProvider={dataProvider}
        layoutProvider={layoutProvider}
        rowRenderer={rowRenderer}
        scrollViewProps={{showsVerticalScrollIndicator: false}}
        style={{flex: 1, marginTop: 20}}
      />
      <Portal>
        <ModalDrops DropInfo={dropRef} ref={el => (modals[3] = el)} />
      </Portal>
    </View>
  )
};

ModalDrops

代码语言:javascript
复制
const Item = React.memo(({ name, image, index }) => {
  return (
    <View style={styles.item}>
      ...
    </View>
  )
});

export const ModalDrops = React.forwardRef(({ DropInfo }, ref) => {
  function renderItem({ item, index }) {
    return <Item name={item.name} image={item.image} index={index} />
  };

  ...

  return (
    <Modalize
      ref={ref}
      modalHeight={300}
      flatListProps={{
        data: DropInfo.monster,
        style: {
          padding: 8,
          flex: 1
        },
        renderItem: renderItem,
        horizontal: true,
        ListEmptyComponent: () => {
          return (
            <View style={styles.itemEmpty}>
              <Text>Nicht Droppbar</Text>
            </View>
          )
        },
        keyExtractor: key,
        showsHorizontalScrollIndicator: false,
        scrollEventThrottle: 16,
        contentContainerStyle: {
          justifyContent: 'center',
          alignItems: 'center'
        }
      }}
    />
  )
});
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69816993

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档