Reputation: 565
I'm learning react native by building a simple chat app. I have two screens wrapped in a TabNavigator where the first screen (Screen A) being the chatbox, and the other screen (Screen B) which displays a list of online users. I'm using SocketIO to fetch these users.
Problem is, how can I access the "onlineUsers" state from ScreenA to ScreenB so I can see an updated list of online users whenever I receive a "user joins" event?
Screen 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
})
})
}
}
Screen B:
export default class ScreenB extends Component {
constructor(props) {
super(props);
// I want to get the onlineUsers from ScreenA
this.state = {
onlineUsers = [];
}
}
}
Router:
export const Chat = TabNavigator({
ChatBox: {
screen: ScreenA
},
OnlineUsers: {
screen: ScreenB
},
})
PS: I'm using react-navigation to handle navigation
Upvotes: 4
Views: 3352
Reputation: 5626
I came across this post when I ran into a similar issue earlier this year so I thought I'd post my solution.
I would say your best bet in this situation is to use a Custom Navigator to wrap your TabNavigator which will expose <TabNavigator />
in your custom navigator allowing you to pass any methods or state down to ScreenA
and ScreenB
as screenProps
.
The custom navigator would look like:
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
From here you could implement an event system as @Ashish Prakash suggested, or manage all of your state in the custom navigator and transform ScreenA
and ScreenB
into presentational components.
Upvotes: 0
Reputation: 2326
Use this.props.navigation.setParam({onlineUsers: onlineUsers: payload.users})
when you get user-list from server.
Then use it in Screen B like this.props.navigation.state.params.onlineUsers
Upvotes: -1
Reputation: 235
Best way is to handle events in the parent component and then passing it to their children components. So in your case, you should have a online user list in your router. Then pass the array to screen B. Here is how you should do
Router
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}>
},
})
Screen 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)
})
}
}
Screen B
export default class ScreenB extends Component {
constructor(props) {
super(props);
}
// You can access online user using this.props.userList
}
Upvotes: 3