React Native:如何从子组件中的父组件访问变量? [英] React Native: How to access a variable from parent component in child component?

查看:74
本文介绍了React Native:如何从子组件中的父组件访问变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将newsocket变量从MessagesScreen.js传递到ChatScreen.js.

i am trying to pass my newsocket variable from my MessagesScreen.js to my ChatScreen.js.

我在这一点上停留了一段时间,希望对您有所帮助.我要实现的目标是仅发出一个连接,我可以在两个屏幕上收听事件.

I have been stuck on this point for a while and would appreciate any help possible. What i am trying to achieve is that only one connection gets emitted which i can listen to events on both screen.

现在在messagesScreen中打开了连接.我现在的问题是用户1是否在allmessages屏幕上,而用户2是否在聊天窗口中.并且用户2向用户1发送了一条消息,用户1的屏幕不会自动更新为该消息发送到的对话的最后一条消息,我需要滚动刷新以刷新或从一个页面导航到另一页面才能显示

The connection is now opened on the messagesScreen. My problem now is if user 1 is on the allmessages screen and user 2 is inside the chat. And user 2 sends user 1 a message, user 1's screen does not automatically update with the last message for the conversation the message was sent to, I need to either scroll to refresh or navigate from one page to the other in order for it to appear.

这是我的代码:

父母-> messagesScreen.js

PARENT --> messagesScreen.js

function MessagesScreen({navigation}) {
const [posts, setPosts] = useState([]);
const { user } = useAuth();
const [socket, setSocket] = useState(null);

const loadposts = async () => {
const response = await messagesApi.getMessages();// here i am loading all the conversation this user has
setPosts(response.data)
};

useEffect(() => {

newsocket = sockets(user.id); // newsocket is what i am trying to pass to child component
setSocket(newsocket);

loadPosts()

newsocket.on("send_message", (msg) => {
  console.log("messages:", msg);
})

}, []);

return (
<FlatList
    data={posts}
    keyExtractor={(post) => post.id.toString()}
    renderItem={({ item,index }) => (
      <MessagesList
      title={item.Post.title}
        subTitle={item.Messages[0].message}
        onPress={() => navigation.navigate(
                routes.CHAT,{message:item,index,newsocket:socket})}
      />
    )}
  />
)

孩子---> chatScreen.js

CHILD ---> chatScreen.js

function ChatScreen({route,navigation,socket}) {  
const [messages, setMessages] = useState([]);
const { user } = useAuth();

  const index = route.params.index;
  const message = route.params.message;
  const newsocket = route.params.newsocket;

  const loadListings = async () => {
  const response = await messagesApi.getConversation(message.id);// here i am loading the messages in that specific conversation
  setMessages(response.data.Messages)
  };

 useEffect(() => {
 loadListings()
 newsocket.emit('subscribe', message.id);

 newsocket.on("send_message", (msg) => {
    console.log("this is the chat messages:", msg);
    setMessages(messages => [msg, ...messages]);
  });
  }, []);

 const onSend = (ConversationId,senderId,receiverId,message) => {

const to = (user.id===route.params.message.user1? 
route.params.message.user2:route.params.message.user1)

socket.emit('message', { to: to, from: user.id, message,ConversationId});

messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
};

return(
 <FlatList
    inverted
    data={messages}
    keyExtractor={(item,index)=>index.toString()}
    extraData={messages} // add this    
    renderItem={({item,index})=>(
        <MessageBubble
        text={item.message}
        mine={item.senderId !== user.id}
        />
    )}
    />
)

socket.js

socket.js

import io from 'socket.io-client';

const newsocket = (user) => {
let newsocket = io.connect("http://192.168.1.107:9000")

newsocket.on('connect', msg => {
console.log(`waiting for user: ${user} to join a conversation`)
});

newsocket.emit('waiting', user);

return newsocket;
}

export default newsocket;

推荐答案

我会采取不同的方法.

  1. 您可以在单独的模块中将套接字连接创建为共享服务,然后将其简单地导入所需的相关组件中.在此共享模块中,您将处理连接/断开连接并返回现有连接或创建新连接以返回.

快速粗加工:

// socket-server.ts
import io from 'socket.io-client';

let socket: SocketIOClient.Socket = null;

export const getSocketServer = (): Promise<SocketIOClient.Socket> => {
    return new Promise<SocketIOClient.Socket>(resolve => {
        if (socket) {
            console.info(`returning existing socket: ${socket.id}`);

            return resolve(socket);
        }

        socket = io('http://localhost:4000', {
            autoConnect: false,
        });

        socket.on('connect_error', (err) => {
            console.error(err);
        })

        socket.on('connect', () => {
            console.info(`creating new socket: ${socket.id}`);

            return resolve(socket);
        });

        socket.open();
    })
}

// then in your relevant modules
// module-a.ts
import React, {useEffect, useState} from 'react';
import {getSocketServer} from './../components/socket-server';

const Component = () => {
    useEffect(() => {
        const connect = async () => {
            const socket = await getSocketServer();

            socket.on('hello', (message) => {
                console.info('hello from module A', message);
            });
        }
        connect();
    }, []);

    return (
        <>
            <h2>Module A</h2>
        </>
    )
}

export default Component;

  1. 您也许还可以考虑创建一个上下文提供程序,并与相关模块共享套接字根据需要.
  1. You could maybe also look at creating a Context Provider and share the socket with relevant modules as needed.

上下文提供了一种通过组件树传递数据的方法,而无需 必须在每个级别手动传递道具.

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

这篇关于React Native:如何从子组件中的父组件访问变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆