【问题标题】:React Navigation: Share state between two screens within TabNavigatorReact Navigation:在 TabNavigator 中的两个屏幕之间共享状态
【发布时间】:2018-01-18 03:04:51
【问题描述】:

我正在通过构建一个简单的聊天应用来学习 React Native。我有两个屏幕包裹在 TabNavigator 中,其中第一个屏幕(屏幕 A)是聊天框,另一个屏幕(屏幕 B)显示在线用户列表。我正在使用 SocketIO 来获取这些用户。

问题是,如何访问从 ScreenA 到 ScreenB 的“onlineUsers”状态,以便在收到“用户加入”事件时看到更新的在线用户列表?

屏幕 A:

export default class ScreenA extends Component {
  constructor(props) {
    super(props);

    this.state = {
      onlineUsers = [];
    }
  }

  componentDidMount() {
    // Update list of online users when new user joins chat
    this.socket.on('user joins', (payload) => {
      this.setState({
        onlineUsers: payload.users
      })
    })
  }
}

屏幕 B:

export default class ScreenB extends Component {
  constructor(props) {
    super(props);

    // I want to get the onlineUsers from ScreenA
    this.state = {
      onlineUsers = [];
    }
  }
}

路由器:

export const Chat = TabNavigator({
  ChatBox: {
   screen: ScreenA
  },
  OnlineUsers: {
   screen: ScreenB
  },
})

PS:我正在使用 react-navigation 来处理导航

【问题讨论】:

    标签: react-native socket.io react-navigation


    【解决方案1】:

    最好的方法是在父组件中处理事件,然后将其传递给它们的子组件。因此,在您的情况下,您的路由器中应该有一个在线用户列表。然后将数组传递给屏幕 B。这是你应该怎么做的

    路由器

    state = {
        online_users:[]
    }
    
    _update = (data) => {
        this.setState({online_users:data});
    };
    
    export const Chat = TabNavigator({
       ChatBox: {
           screen: <ScreenA onUpdate={this._update}/>
        },
        OnlineUsers: {
           screen: <ScreenB userList={this.state.online_users}>
        },
    })
    

    屏幕 A

    export default class ScreenA extends Component {
        constructor(props) {
            super(props);
        }
    
        componentDidMount() {
            // Update list of online users when new user joins chat
            this.socket.on('user joins', (payload) => {
                this.props.onUpdate(payload.users)
            })
        }
    }
    

    屏幕 B

    export default class ScreenB extends Component {
        constructor(props) {
            super(props);
        }
    
        // You can access online user using this.props.userList
    
     }
    

    【讨论】:

    • 除了&lt;ScreenA /&gt;无效——它只会接受ScreenA,不允许传递额外的props。
    【解决方案2】:

    我在今年早些时候遇到类似问题时偶然发现了这篇文章,所以我想我会发布我的解决方案。

    我想说,在这种情况下,您最好的选择是使用自定义导航器来包装您的 TabNavigator,这将在您的自定义导航器中公开 &lt;TabNavigator /&gt;,从而允许您将任何方法或状态传递给 ScreenAScreenB 作为screenProps.

    自定义导航器如下所示:

    import React from 'react'
    import { ChatTabNavigator } from './ChatTabNavigator'
    
    class StateManagingCustomNavigator extends React.Component {
      static router = ChatTabNavigator.router
    
      state = {
        onlineStatus: [theStatus]
      }
    
      handleMessagePosted = () => {
        // Handle message post, etc...
      }
    
      // ... SocketIO code and other logic to manage the state here? ...
    
      render() {
        const { navigation } = this.props
        const { onlineStatus } = this.state
    
        return (
          <ChatTabNavigator
           screenProps={{
             theStatus: onlineStatus,
             chatMessagePosted: this.handleMessagePosted
           }}
           navigation={navigation}
          />
        )
      }
    }
    
    export default StateManagingCustomNavigator
    

    从这里您可以按照@Ashish Prakash 的建议实现一个事件系统,或者在自定义导航器中管理您的所有状态并将ScreenAScreenB 转换为演示组件。

    【讨论】:

      【解决方案3】:

      从服务器获取用户列表时使用this.props.navigation.setParam({onlineUsers: onlineUsers: payload.users})

      然后像this.props.navigation.state.params.onlineUsers一样在屏幕B中使用它

      【讨论】:

      • 这是错误的。这些参数仅在一条路线内保持一致,而不是在两个屏幕上保持一致。看到这个小吃:snack.expo.io/rJvG78XIQ
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-17
      • 2019-07-04
      • 2020-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多