我有一个列表与回收列表视图,在那里你可以点击一个项目,然后一个模式是打开的,在模式是与扁平列表的项目。所以如果我打开模式,它会重现2-3倍。如果我再次滚动或单击它的重现程序。但是为什么呢?我使用react.memo
回收器列表视图
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>
)
};模态平面列表:
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 ....................................................................................................................
发布于 2021-11-02 22:40:38
问题
在我看来,声明Item组件的方式有一个主要问题,它是在另一个组件内部声明的,因此在任何时候外部组件呈现时,它都会重新声明。这有效地卸载了以前的“实例”,并挂载了一个新的“实例”。从技术上讲,它不是重新渲染,它只是完全重新挂载。
解决方案
不要在其他React组件中声明React组件。在这样做的时候,和试图记录任何渲染结果都不会起作用,因为每个渲染周期都会创建并挂载一个新组件。将Item声明移到组件之外。
老板们
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
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'
}
}}
/>
)
});https://stackoverflow.com/questions/69816993
复制相似问题