Javascript React Native:如何从子组件中的父组件访问变量?

Javascript React Native:如何从子组件中的父组件访问变量?,javascript,react-native,socket.io,Javascript,React Native,Socket.io,我正在尝试将newsocket变量从MessagesScreen.js传递到ChatScreen.js 我已经在这一点上停留了一段时间,并将感谢任何可能的帮助。我试图实现的是,只发出一个连接,我可以监听两个屏幕上的事件 连接现在在messagesScreen上打开。我现在的问题是,如果用户1在allmessages屏幕上,而用户2在聊天室中。用户2向用户1发送消息,用户1的屏幕不会自动更新消息发送到的对话的最后一条消息,我需要滚动刷新或从一个页面导航到另一个页面才能显示 这是我的密码: 父-->

我正在尝试将newsocket变量从MessagesScreen.js传递到ChatScreen.js

我已经在这一点上停留了一段时间,并将感谢任何可能的帮助。我试图实现的是,只发出一个连接,我可以监听两个屏幕上的事件

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

这是我的密码:

父-->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
屏幕中传递变量并进行访问

MessagesScreen.js

routes.CHAT,{message:item,index,updateView, newsocket})}
const newsocket = route.params.newsocket;
 ....

newsocket.emit('subscribe', message.id);  // call like this
chatScreen.js

routes.CHAT,{message:item,index,updateView, newsocket})}
const newsocket = route.params.newsocket;
 ....

newsocket.emit('subscribe', message.id);  // call like this

我会以不同的方式来处理这个问题

  • 您可以在单独的模块中将套接字连接创建为共享服务,并将其导入所需的相关组件中。在此共享模块中,您可以处理连接/断开连接并返回现有连接或创建新连接以返回
  • 快速粗加工:

    // 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;
    
    //socket-server.ts
    从“socket.io客户端”导入io;
    let socket:SocketIOClient.socket=null;
    export const getSocketServer=():Promise=>{
    返回新承诺(解决=>{
    中频(插座){
    info(`返回现有套接字:${socket.id}`);
    返回解析(套接字);
    }
    套接字=io('http://localhost:4000', {
    自动连接:错误,
    });
    socket.on('connect_error',(err)=>{
    控制台错误(err);
    })
    socket.on('connect',()=>{
    info(`creatingnewsocket:${socket.id}`);
    返回解析(套接字);
    });
    socket.open();
    })
    }
    //然后在你的相关模块中
    //模块a.ts
    从“React”导入React,{useffect,useState};
    从“/../components/socket server”导入{getSocketServer};
    常量组件=()=>{
    useffect(()=>{
    const connect=async()=>{
    const socket=wait getSocketServer();
    socket.on('hello',(message)=>{
    console.info(“模块A的你好”,消息);
    });
    }
    connect();
    }, []);
    返回(
    模块A
    )
    }
    导出默认组件;
    
  • 您还可以根据需要创建一个套接字并与相关模块共享该套接字
  • 上下文提供了一种通过组件树传递数据的方法,而无需 必须在每一个关卡手动传递道具


    嗨Mehran谢谢你回复我。在MessagesScreen inside中,当我
    console.log(newsocket)
    获取套接字对象时,使用效果有效;但当我
    console.log(newsocket)
    获取未定义的
    时,使用聊天屏幕。您也可以使用Redux。请通过这个@swand嗨,谢谢你回复我。有没有可能在没有redux的情况下实现这一点?请格式化代码以便于阅读。嗨,塞缪尔,谢谢你回复我。这不是我在socket.js顶部所做的吗?在这里,我在socket.js中创建连接,并将socket.js导入父组件。我有一个简单的问题:在我的父组件中的
    useffect
    中,当我设置
    setSocket(newsocket)
    时;如果我在之后尝试访问套接字状态变量(即,
    socket
    ),它是否也应该等于
    newsocket
    ?您希望能够在整个应用程序中共享此套接字服务-将其视为DB连接。这是一种典型的服务模式。任何时候状态改变或组件重新呈现变量:
    var socket
    都将重新定义。如果您不完全了解状态如何更改以及组件如何重新渲染,请花点时间阅读。PS-在
    socket.js
    中,您应该在开始发射之前确保连接。嗨,Samuel,我格式化了我的代码,使之更简单,并用我最近的更改对其进行了更新。当前,当我重新加载我的应用程序并转到父屏幕时,使用上面的代码,然后建立连接如果我离开此屏幕转到任何其他屏幕,然后返回,则连接仍然打开,不会关闭,然后再次打开。此外,my allMessages屏幕中的套接字侦听器当前正在侦听与聊天屏幕上相同的事件(send_message),这是否意味着我的套接字正在工作?是的,如果您在客户端上导航,它不应关闭和打开。如果确实希望它关闭,则对共享服务调用close方法。是的,所有注册侦听器的组件都将接收消息-这允许您在相关模块中以不同方式处理它们。