我正在使用Expo(React Native框架)编写应用程序。每当使用setState(...)方法更改组件的状态时,组件都应重新渲染以显示最新的状态数据。这适用于基本的React Native组件,例如View,Text,Button(我已经尝试了这三个组件),但是在这里我没有使用自定义组件TabView进行重新渲染。有关组件的文档中对此进行了说明:
“使用SceneMap渲染的所有场景均使用React.PureComponent进行了优化,并且在父项的道具或状态发生更改时不会重新渲染。如果您需要更多控制场景更新方式的信息(例如-即使发生触发重新渲染navigationState不变),请直接使用renderScene而不是使用SceneMap。“
我不太了解如何进行管理。我希望在状态更改时重新渲染组件,在这种情况下,在单击按钮并调用函数writeData()之后。
TabView组件的文档在这里:https://github.com/react-native-community/react-native-tab-view。
import React from 'react';
import { TabView, SceneMap } from 'react-native-tab-view';
import { StyleSheet, Text, View, Dimensions, Button, ToastAndroid } from 'react-native';
export default class MojTabView extends React.Component {
state = {
index: 0,
routes: [
{ key: 'allEvents', title: 'Všetko' },
{ key: 'sortedEvents', title: 'Podľa druhu' },
{ key: 'myEvents', title: 'Moje akcie'}
],
name: "Robert"
};
MyEvents = () => (
<View style={[styles.scene, { backgroundColor: 'white' }]}>
<Text>Some content</Text>
<Button
style={{ margin: 5 }}
onPress={this.writeData}
title="Write data"
color="#841584"
/>
<Text>Name in state: {this.state.name}</Text>
</View>
);
SortedEvents = () => (
<Text>Some content</Text>
);
AllEvents = () => (
<Text>Some other content</Text>
);
writeData = () => {
ToastAndroid.show("button click works!", ToastAndroid.LONG);
this.setState({ name: "Richard"});
}
render() {
return (
<TabView
navigationState={this.state}
renderScene={SceneMap({
allEvents: this.AllEvents,
myEvents: this.MyEvents,
sortedEvents: this.SortedEvents
})}
onIndexChange={index => this.setState({ index })}
initialLayout={{ width: Dimensions.get('window').width }}
/>
);
}
}
我花了几个小时试图实现这一目标,但没有解决方案。这是我的第一个StackOverflow问题,谢谢。
答案 0 :(得分:1)
好的,我终于能够提出一个不错的解决方案。关键是要在一个单独的文件中将各个选项卡/路由的内容定义为具有自身状态的典型React Native组件,而不是在此MyTabView组件内部,就像在TabView文档中的示例中所做的那样。然后它会按预期工作。
简单的例子: 这是选项卡之一的内容:
import React from 'react';
import { Text, View, Button } from 'react-native';
export default class MyExampleTab extends React.Component {
state = {
property: "Default value",
}
writeData = () => {
this.setState({
property: "Updated value"
})
}
render() {
return (
<View>
<Button
style={{ margin: 5 }}
onPress={this.writeData}
title="Change the state and re-render!"
color="#841584"
/>
<Text>Value of state property: {this.state.property}</Text>
</View>
)
}
}
这是我在MyTabView组件中引用它的方式:
import MyExampleTab from './MyExampleTab'
...
export default class MyTabView extends React.Component {
...
render() {
return (
<TabView
navigationState={this.state}
renderScene={SceneMap({
...
someKey: MyExampleTab,
...
})}
onIndexChange={index => this.setState({ index })}
initialLayout={{ width: Dimensions.get('window').width }}
/>
)
因此,我不像通常使用自定义组件那样使用<MyExampleTab />
,而是按原样编写MyExampleTab
。这很有意义。然后在按钮上单击状态更改,然后重新渲染选项卡。
答案 1 :(得分:0)
应重新触发TabView
的两种状态是:
他们这样做是出于性能优化的目的
如果您要在更改与这些值无关的任何其他状态值时强制重新渲染TabView
,则根据文档...您需要提供renderScene
自己的实现,例如:
renderScene =({route,jumpTo})=> { 切换(route.key){ 案例“音乐”: 回报; 案例“相册”: 回报; } };
在这种情况下:
您需要确保您的个人路线实施了 应该改善组件的性能。
答案 2 :(得分:0)
以@druskacik上面的内容为基础,实际上您也可以传递带有道具的组件
import MyExampleTab from './MyExampleTab'
...
export default class MyTabView extends React.Component {
...
render() {
return (
<TabView
navigationState={this.state}
renderScene={SceneMap({
...
someKey:() => <MyExample foo={foodata} />,
...
})}
onIndexChange={index => this.setState({ index })}
initialLayout={{ width: Dimensions.get('window').width }}
/>
)