如何正确更新/重新渲染不是子级React Native的组件?

时间:2018-08-14 00:12:30

标签: reactjs react-native react-navigation

我正在使用反应导航。更具体地说,我将一个materialTabNavigator嵌套在抽屉导航器内部。每个选项卡本身就是一个stackNavigator。我在homeScreen中有一个按钮,可导航至makePost.js。我在那里接收信息,并使用一个简单的包装将其存储到异步存储中。

在Posts.js中,有一个FlatList将每个帖子作为组件显示。从异步存储发出请求后,最初会正确设置FlatList的数据。问题在于,只有在首次打开应用程序时才会发生这种情况。我尝试了许多不同的方法来解决此问题。到目前为止,我发现的唯一方法是在Posts.js的ComponentDidUpdate()中连续setState。显然,这是有问题的,因为它会不断重新渲染。我可以设置一个标志来阻止正在渲染,但是它不会再次重新渲染。

最终,我想发生的事情是,当我击中用户时,完成输入他们的信息并准备发表的工作,他们击中了makePost.js中的按钮,并击中了FlatList of Posts中的数据。 js是更新。

我尝试使用导航传递参数,但不起作用,参数会丢失,可能是因为嵌套的导航器。

我真的可以使用一些指导来实现这一目标。

(导航器;不确定为什么要强制执行一行)

---抽屉     --tabNav     -家       homeScreen.js       makePost.js
    -帖子       posts.js     -消息   --drawer1   --drawer2

//Posts.js
export default class Posts extends React.Component {
  state = { 
    rows: [
      {id: 0, text: "dog"},
    ],
  }

  componentDidMount() {
    this.loadState();
  }

  loadState = () => {
    var value = store.get('posts').then((res => {
        if (res === null) {
          res = [{id: 0, text: "default"}]
        } else {
          res = res 
        }
        this.setState({rows: res})
    }))
  }

  componentDidUpdate() {
    this.loadState();
  }

  renderItem = ({item}) => {
    return (
      <BoardTab style={styles.row} />
    )} 

  render() {
    return (
      <View style={styles.view}>
        <FlatList
          ListFooterComponent={this.renderFooter}
          style={styles.container}
          data={this.state.rows}
          renderItem={this.renderItem}
          keyExtractor={extractKey}
         >
        </FlatList>
        <BoardScreenFooter />
      </View>
    );
  }

Posts.js按钮如下所示:

        <TouchableOpacity 
            onPress={ () => {
            this._onPressButton
            this.storeFunc(this.state.newPost)
            const retval = this.state.rows

            this.props.navigation.navigate('Board', 
            {rowsID: retval});

            }
          }>
          <Icon
            reverse
            name='md-camera'
            type='ionicon'
            color='green'
          size={12}
          />
        </TouchableOpacity>  



  storeFunc(newObj) {
    newObj.id = newObj.id + 1
    store.push('posts', newObj)
    store.get('posts').then((res) => {
      this.setState({rows: res})
    })
  }

2 个答案:

答案 0 :(得分:0)

我很快会说:使用Redux。它允许您在应用程序中具有全局状态,这意味着您可以在任何地方访问该状态(也可以在任何地方设置它们) 打开应用程序时,您会将数据从AsyncStore获取到Redux存储中。您将聆听redux状态(组件中将是props)并显示您的列表。在其他标签中修改列表时,您需要做两件事:

  1. 将新数据存储在AsyncStorage中
  2. 更新redux存储中的状态。由于Posts.js将在redux商店(作为道具)进行监听,因此每次您的数据更改时,它将重新呈现

答案 1 :(得分:0)

一种在导航到它时重新渲染React-Navigation屏幕视图的简单方法:

一切归功于Andrei Pfeiffer(2018年7月)在他的文章中:“ React Navigation v2中的Handle Tab更改” https://itnext.io/handle-tab-changes-in-react-navigation-v2-faeadc2f2ffe

如果以上链接失效,我将在这里重申。

只需使用所需的侦听器道具将NavigationEvents组件添加到渲染函数中即可:

  render() {
return (
      <View style={styles.view}>
      <NavigationEvents
          onWillFocus={payload => {
            console.log("will focus", payload);
            this.loadState();
          }}
        />
        <FlatList
          ListFooterComponent={this.renderFooter}
          style={styles.container}
          data={this.state.rows}
          renderItem={this.renderItem}
          keyExtractor={extractKey}
        >
        </FlatList>
        <PostScreenFooter />
      </View>
    );
  }