ContextAPI: Как можно обмениваться данными между контекстами в React? - PullRequest
0 голосов
/ 05 марта 2020

Вот моя проблема:

Бит аутентификации моего сайта "завершен". После регистрации / входа пользователь получает повар ie, содержащий токен jwt. После получения UserDataContext получают идентификатор пользователя (uid) и имя пользователя. UID используется для всех видов вещей на сервере.

Socket.io будет использоваться для указания бэкэнду делать вещи из внешнего интерфейса. Разъем доступен для реагирования компонентов через контекст реакции. У меня есть 2 контекста, UserDataContext и SocketContext. Мне нужно отследить, какой разъем подключен к какому пользователю.

Я полагаю, я создам класс SocketManager на сервере, который прослушивает новые соединения с сокетами и связывает их с пользователем с помощью uid. Я попытался сделать это с идентификатором Socket, но проблема в том, что идентификатор изменяется при перенаправлениях / обновлениях. Итак, мне нужен способ отправить UID с событием подключения сокета. Идентификатор пользователя содержится в UserDataContext.

Как мне получить идентификатор пользователя из UserDataContext в SocketContext? Должен ли я объединить эти контексты? Это даже правильное направление?

Приложение. js -

import React, { Component } from 'react';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';

import UserDataContextProvider from './contexts/UserDataContext.js';
import SocketContextProvider from './contexts/SocketContext.js';

import Landing from './pages/Landing.js';
import Topnav from './pages/components/global/Topnav.js';
import UserDashboard from './pages/components/consoles/UserDashboard.js';

import './Global.css';


const App = props => (
  <div>
    <UserDataContextProvider>
      <Topnav />
      <SocketContextProvider>
        <Switch>
          <Route exact path='/' component={Landing} />
          <Route exact path='/dashboard/:id' component={UserDashboard} />
        </Switch>
      </SocketContextProvider>
    </UserDataContextProvider>
  </div>
);

export default App;

UserDataContext. js -

import React, { Component, createContext } from 'react';

export const UserDataContext = createContext();

class UserDataContextProvider extends Component{
  state = {
    auth: false,
    uid: false,
    username: false
  };

  setUserData = data => {
    this.setState({uid: data.uid, username: data.tag})
  }

  render(){
    return (
      <UserDataContext.Provider value={{state: this.state, setUserData: this.setUserData}}>
        {this.props.children}
      </UserDataContext.Provider>
    );
  }
}

export default UserDataContextProvider;

SocketContext. js -

import React, { Component, createContext } from 'react';

export const SocketContext = createContext();

import io from 'socket.io-client';
const prod = (process.env.NODE_ENV === "production");
const address = prod ? window.location.hostname : "http://localhost:8080";
const socket = io(address);

class SocketContextProvider extends Component{
  render(){
    return (
      <SocketContext.Provider value={{socket:socket}}>
        {this.props.children}
      </SocketContext.Provider>
    );
  }
}

export default SocketContextProvider;

1 Ответ

1 голос
/ 05 марта 2020

Вам нужно будет вложить вещи в SocketContextProvider, использующий контекст пользовательских данных (или объединить два провайдера). Затем вы можете:

  • отправить специальное сообщение, информирующее сервер о новом uid, когда он изменяется, или
  • отправить uid в каждом отправляемом вами сообщении

Тем не менее, использование контекстов и провайдеров в основном полезно для распространения изменений состояния (таких как имена пользователей, темы и так далее), а не столько "живых объектов", как этот сокет.

Для вашего случая, так как у вас уже есть глобальный уровень для сокета, не большой грех просто предвидеть go провайдера и контекст для сокета, и просто

import io from 'socket.io-client';
const prod = (process.env.NODE_ENV === "production");
const address = prod ? window.location.hostname : "http://localhost:8080";

let socket = null;

export function getSocket() {
  if(socket === null) {
    socket = io(address);
  }
  return socket;
}

и

import { getSocket } from './socket-things';

const MyComponent = () => (
  <button onClick={() => getSocket().send('foo')} />
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...