pin*_*man 5 modal-dialog reactjs react-native react-animations react-native-modal
我正在尝试构建一个具有左右轮播的反应本机屏幕,在轮播的每个面板中都有一个带有项目列表的垂直平面列表。最多有 8-10 个轮播面板,平面垂直平面列表中最多有 5-30 个项目,因此最多可能有 300 个呈现的项目,但通常为 100 个。
我正在调用 API 并每 2-3 秒检查一次服务器上的数据,并使用新数据设置组件中的状态。目前,此功能有效,并且子组件中的数据会按预期更新。
平面列表中的每个项目都是可单击的,这会触发在页面中启动模式弹出窗口。我遇到的问题是模态弹出窗口需要 4-5 秒才能出现和关闭。此外,当模态最终开始消失时,动画会变得不稳定,并且深色背景层在被删除时似乎会闪烁。
我首先尝试使用内置模态,还使用了react-native-modal 包,两者都是相同的。
我尝试使用 InteractionManager.runAfterInteractions 以及 shouldComponentUpdate(nextProps, nextState) 来尝试阻止我的 api 调用,直到动画完成或阻止我的 isModalVisible 状态属性在我更改它时导致重新渲染。
下面的代码,任何帮助将不胜感激。
import {
Text,
Button,
StyleSheet,
View,
FlatList,
Dimensions,
Image,
Animated,
SafeAreaView,
TouchableHighlight,
InteractionManager,
} from 'react-native';
import React from 'react';
import Title from './Title';
import CarouselMeeting from './CarouselMeeting';
import Modal from 'react-native-modal';
import Carousel from 'react-native-snap-carousel';
class MeetingDisplay extends React.Component {
constructor(props) {
super(props);
this.state = {
raceList: [],
meetingList: [],
meetingId: props.navigation.state.params.meetingId,
currentIndex: 0,
raceCount: 0,
activeIndex: 0,
isModalVisible: false,
}
this.refreshScreen = this.refreshScreen.bind(this)
}
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
Promise.all([fetch('http://apicallurl?id' + this.state.meetingId), fetch('http://apicallurl?id' + this.state.meetingId)])
.then(([res1, res2]) => {
return Promise.all([res1.json(), res2.json()])
})
.then(([res1, res2]) => {
this.setState({
raceList: res1,
meetingList: res2.Meets,
})
});
this.interval = setInterval(() => this.updateRaceList(), 3000);
});
}
componentDidUpdate(prevProps, prevState) {
InteractionManager.runAfterInteractions(() => {
if (prevState.meetingId !== this.state.meetingId) {
Promise.all([fetch('http://apicallurl?id' + this.state.meetingId), fetch('http://apicallurl?id' + this.state.meetingId)])
.then(([res1, res2]) => {
return Promise.all([res1.json(), res2.json()])
})
.then(([res1, res2]) => {
this.setState({
raceList: res1,
meetingList: res2.Meets,
})
});
}
});
}
async updateRaceList() {
InteractionManager.runAfterInteractions(() => {
fetch('http://apicallurl' + this.state.meetingId)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
raceList: responseJson,
}, function () {
});
})
.catch((error) => {
console.error(error);
});
});
}
toggleModal = () => {
InteractionManager.runAfterInteractions(() => {
this.setState({ isModalVisible: !this.state.isModalVisible });
});
};
shouldComponentUpdate(nextProps, nextState) {
if(this.state.isModalVisible !== nextState.isModalVisible){
this.setState({ isModalVisible: nextState.isModalVisible})
return false;
} else return true;
}
render() {
const peek = 20;
const gutter = peek / 4;
const cardWidth = Dimensions.get('window').width - gutter * 2 - peek * 2;
const contentOffset = (Dimensions.get('window').width - (cardWidth + (gutter * 2))) / 2;
return (
<>
<Title heading={this.state.raceList.VenueName} />
<SafeAreaView style={{ flex: 1, backgroundColor: 'rebeccapurple', paddingTop: 50, }}>
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center', }}>
<Carousel
layout={"default"}
useScrollView
ref={ref => this.Carousel = ref}
data={this.state.raceList.RaceList}
sliderWidth={cardWidth}
itemWidth={cardWidth - gutter * 2 - peek * 2}
onSnapToItem={index => this.setState({ activeIndex: index })}
renderItem={({ item }) => (
<Animated.View style={{
flex: 1,
paddingTop: 20,
width: cardWidth,
margin: gutter,
backgroundColor: 'blue',
justifyContent: 'center',
alignItems: 'center',
}}>
<FlatList
horizontal={false}
showsVerticalScrollIndicator={true}
legacyImplementation={false}
data={item.runner_list}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }, index) =>
<TouchableHighlight style={{ flex: 1, flexDirection: 'row' }} onPress={this.toggleModal} >
<Image style={{ width: 50, height: 50 }} source={{ uri: item.imageurl }} />
</TouchableHighlight>}
>
</FlatList>
</Animated.View>
)}
/>
</View>
</SafeAreaView>
<Modal isVisible={this.state.isModalVisible}
backdropTransitionOutTiming={1}>
<View style={{ flex: 1 }}>
<Text>Hello!</Text>
<Button title="Hide modal" onPress={this.toggleModal} />
</View>
</Modal>
</>
);
}
}
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5
},
openButton: {
backgroundColor: "#F194FF",
borderRadius: 20,
padding: 10,
elevation: 2
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center"
},
modalText: {
marginBottom: 15,
textAlign: "center"
}
});
export default MeetingDisplay;
Run Code Online (Sandbox Code Playgroud)
尝试1
我有一个想法,这可能是我使用了一个名为“react-native-snap-carousel”的第三方轮播库,所以我尝试用一个看起来很糟糕的滚动视图替换它,并将我所有的平面列表/项目渲染在其中,但这确实没有改善弹出时间延迟,仍然是 2-3 秒。
尝试2
我发现了一个名为react.purecomponent的东西,它可能应该对状态/道具进行浅层比较,并且仅在项目/状态实际发生变化时才触发重新渲染,这可能意味着动画/ui线程无论是什么导致问题停止。但再好不过了(无论是在模拟器上还是在设备上)在模态显示之前仍然长时间暂停
class MeetingDisplay extends React.PureComponent
Run Code Online (Sandbox Code Playgroud)
尝试4
通过在底部轮播下方的页面底部放置一个按钮来触发平面列表外部的模式,从而将平面列表从等式中取出。
....</View>
</SafeAreaView>
<Modal
visible={this.state.isModalVisible}
backdropTransitionOutTiming={1}
>
<View style={{ flex: 1 }}>
<Text>Hello!</Text>
<Button title="Hide modal" onPress={this.toggleModal} />
</View>
</Modal>
<Button title="Show modal" onPress={this.toggleModal} />
</>
);....
Run Code Online (Sandbox Code Playgroud)
这没有带来任何改进或性能。那么还有什么原因导致了这个问题。是因为间隔导致我的组件不断重新渲染吗?所以必须有一种方法来暂停我缺少的组件重新渲染。任何人?
ali*_*636 13
我遇到了同样的问题,并通过在模态中添加以下道具来解决它
useNativeDriver={true}
Run Code Online (Sandbox Code Playgroud)
请参考这个对我有帮助的答案, /sf/answers/4341463731/
归档时间: |
|
查看次数: |
12414 次 |
最近记录: |