如何更新另一个选项卡的状态

时间:2015-11-03 06:57:00

标签: tabs react-native

我在TabBarIOS旁边有两个标签。

第一个标签是提供功能,用于将新项目添加到AsyncStorage

第二个标签显示AsyncStorage中的所有项目

但是当我运行我的应用程序时,在第一个选项卡中添加一个新项目后,导航到第二个选项卡,我看不到页面重新渲染,我将需要执行一个Command + R然后我看到我的新数据。< / p>

解决此问题的一种方法是在shouldComponentUpdate中读取asyncStorage,但请注意,反应会不断调用shouldComponentUpdate。虽然我只想强制按需更新UI。

因此,在本机反应中,更新另一个UI组件状态的正确方法是什么?

示例应用: https://drive.google.com/file/d/0B8kAIsj2xDnUMklIQmc0b3NiSVE/view?usp=sharing

2 个答案:

答案 0 :(得分:3)

这就是我正在谈论的内容。一旦完成,你可能想稍微重构一下,但总的来说,我认为最终会看到这种情况。关于正确使用生命周期功能,我还有很多东西需要学习,而且我现在还不确定你是否需要它们。

appContainer.js

我基本上删除了你的NavigatorIOS。我认为这是一个错误。相反,我用组件替换它们,将数据作为道具传递下去,包括按下按钮的回调函数。我已经将addData函数移动了一个级别。

class AppContainer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            selectedTab: 'data-list',
            dataLen: 0
        }

        AsyncStorage.getItem("all-data")
            .then((data)=>{
                if(!data)
                {
                    data = "[]";
                }

                var dataObj = JSON.parse(data);
                this.setState({
                    dataLen : dataObj.length
                });
            });

        this.addData.bind(this);
    }

    addData() {
        AsyncStorage.getItem("all-data")
            .then((data)=>{
                if(!data)
                {
                    data = "[]";
                }

                var dataObj = JSON.parse(data);
                dataObj.push({
                    val: Date.now()
                });

                AsyncStorage.setItem("all-data", JSON.stringify(dataObj));
                this.setState({
                    dataLen: dataObj.length
                });
            });
    }

    render() {
        return (
        <TabBarIOS style={styles.container}>
            <TabBarIOS.Item
                title="Add Data"
                selected={this.state.selectedTab == 'add-data'}
                onPress={()=> this.setState({selectedTab: 'add-data'})}
            >
                <AddData onButtonPress={this.addData} dataLen={this.state.dataLen} />
            </TabBarIOS.Item>
            <TabBarIOS.Item
                title="Data List"
                selected={this.state.selectedTab == 'data-list'}
                onPress={()=> this.setState({selectedTab: 'data-list'})}
                badge={this.state.dataLen}
            >
                <DataList dataLen={this.state.dataLen} />
            </TabBarIOS.Item>
        </TabBarIOS>
      );
    }
}

addData.js

这将显着简化您的子组件...

class AddData extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <View style={styles.container}>
                <Text>{this.props.dataLen}</Text>
                <TouchableHighlight
                    onPress={this.props.onButtonPress}
                    style={styles.button}>
                    <Text style={styles.buttonText}>Plus One</Text>
                </TouchableHighlight>
            </View>
        );
    }


}

dataList.js

class PlayerList extends Component {
    constructor(props) {
        super(props);

    }


    render() {
        return (
            <View style={styles.container}>
                <Text>{this.props.dataLen}</Text>
            </View>
        );
    }
}

答案 1 :(得分:2)

使用Redux

你有没有考虑过使用Redux或同等的东西? 我有同样的问题。最终使用Redux为我解决了它。

官方文件

我强烈推荐您使用Redux的official documentation

实施例

我不会尝试教你Redux,因为文档已经非常好了。但我会尝试概述一些部分,让您了解如何使用Redux。我真的无法更新您现有的应用程序,因为这不是一个微不足道的调整。如果大多数变化对你来说都很神秘,那就不够了。

操作创建者中,您需要致电AsyncStorage并使用 reducer 中的值来更新您的州。重要的部分是组件与Redux存储的连接。您必须将其与自NavigatorIOS doesn't update when passProps update以来通过NavigatorIOS加载的组件相关联。

<NavigatorIOS
      initialRoute={{
        component: MyView,
        title: 'My View Title',
      }}
    />

// MyView Component
...
class MyView extends Component {
...
}

// Prepare the information of the global state and only pass the relevant values as `props` to the component.
function mapStateToProps(state) {
  const { isFetching, isError, lastUpdated } = state.posts;
  const { entities: posts } = state.posts || { entities: {} };

  return {
    posts,
    isFetching,
    isError,
    lastUpdated
  }
}
export default connect(mapStateToProps)(MyView);