How to share a websocket between components - javascript

I have been studying React for two weeks, and have encountered a problem that I do not know how to solve.
My project is a simple app to talk with other people.
I use to communicate with the server WebSocket, but i do not know how to share one connection of socket between all components in the project.
I tried to write a .js file to share socket by simple export and import this variable to other components, it works but only only in the functions not included in the component.
SocketProvider.js
let socket = new WebSocket("ws://ip:65000/srv");
export default socket;
I need this to properly redirect the user to the appropriate project component.
Login.js
import React, {Component} from 'react';
import {Link} from "react-router-dom";
import socket from "./SocketProvider";
import { Redirect } from 'react-router-dom';
class Login extends Component {
state = {
logged: false
};
login = () => {
const loginInput = document.querySelector('#loginInput').value;
const passwordInput = document.querySelector('#passwordInput').value;
const loginData = {
"type": "login",
"name": loginInput,
"password": passwordInput
}
socket.onopen = () => {
socket.send(JSON.stringify(loginData));
}
socket.onmessage = (e) => {
const socketResponse = JSON.parse(e.data);
const status = socketResponse.status;
if(status==4)
this.setState({logged: true});
};
};
render() {
const { logged } = this.state;
if(logged){
return <Redirect to={"/app"}/>
}
return (
<div>
<div className={"whateverInterface"}>
<h1 className={"whateverInterface__logo"}>LOGIN</h1>
<div className={"whateverInterface__form"}>
<div className="whateverInterface__form--object">Login</div>
<input type="text" className={"whateverInterface__input"} id={"loginInput"}/>
<div className="whateverInterface__form--object">Hasło</div>
<input type="password" className={"whateverInterface__input"}id= {"passwordInput"}/>
</div>
<button className={"whateverInterface__button"} id={"createAccountBtn"}
onClick={this.login}>Login
</button>
<div className={"whateverInterace__controls"}>
</div>
</div>
</div>
);
}
}
export default Login
App.js
import React, {Component} from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import logo from './logo.svg';
import { TransitionGroup, CSSTransition } from "react-transition-group";
import './App.css';
import Error404 from './Error404';
import Login from "./Login";
import Main from "./Main";
import socket from "./SocketProvider";
import Register from "./Register";
import AppInterface from "./Interface";
class App extends Component {
constructor() {
super();
this.state = {
isLogged: true
};
}
render() {
return (
<main>
<Route
render={({location}) => {
const {pathname} = location;
return (
<TransitionGroup>
<CSSTransition
key={pathname}
classNames="fade"
timeout={{
enter: 350,
exit: 350,
}}
>
<Route
location={location}
render={() => (
<Switch>
<div className={"content"}>
<Route path="/whatever-react" component={Main} isLogged={this.state.isLogged} exact />
<Route path="/login" component={Login} exact/>
<Route path="/register" component={Register} exact/>
<Route path="/app" component={AppInterface} exact/>
<Route path='*' exact={true} component={Error404}/>
</div>
</Switch>
)}
/>
</CSSTransition>
</TransitionGroup>
);
}}
/>
</main>
);
}
}
export default App;
App.js is the main component with Route, and Login.js is the component when i tried use socket to properly login to my app. Where do i make a mistake?

Related

React-router-dom Protected Routes are not working

Protected Routes.js:
In protected routes you can see I'm using directly false in if statement but I'm still able to see that page why?
import React from 'react';
import { Route } from 'react-router-dom';
// import Auth from './User/Auth';
import Error401 from './Error/401';
// create a component for protected route
console.log('Routes.js');
export const ProtectedRoute = ({ element: Element, ...rest }) => {
console.log("Function Called")
return (
<Route {...rest} render={props => {
if(false){
return <Element {...props} />
}else{
return <Error401 />
}
}
} />
)
}
App.js:
This is app.js where I'm using protected routes component
import './App.css';
import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { Layout } from 'antd';
import { MoneyCollectOutlined } from '#ant-design/icons';
import Login from './Components/User/Login';
import Signup from './Components/User/Signup';
import {ProtectedRoute} from './Components/Routes';
import Error404 from './Components/Error/404';
function App() {
return (
<BrowserRouter>
<Layout style={{minHeight:"100vh"}}>
<Layout.Header>
<h1 style={{color:"white"}} align="center"> <MoneyCollectOutlined/>MoneyG</h1>
</Layout.Header>
<Layout.Content style={{minHeight:"100%"}}>
<Routes>
<ProtectedRoute exact path="/register" element={<Signup/>} />
<ProtectedRoute exact path="/login" element={<Login/>} />
<Route path="*" element={<Error404/>} />
</Routes>
</Layout.Content>
</Layout>
</BrowserRouter>
);
}
export default App;
First, <Routes> elements should only have <Route> elements as children. You should move your protection logic down a layer.
Secondly, the render prop doesn't exist anymore in V6. It was replaced in favor of element. See doc.
Here is how you might tackle it:
<Routes>
<Route exact path="/register" element={(
<ProtectedRoute>
<Signup/>
</ProtectedRoute>
)} />
<Route exact path="/login" element={(
<ProtectedRoute>
<Login/>
</ProtectedRoute>
)} />
<Route path="*" element={<Error404/>} />
</Routes>
And:
const ProtectedRoute = () => {
if (condition) { return <Error401 />; } // You might as well use Navigate here
return children;
};
you can use createContext & useContext
//store/AuthApi.jsx
import { createContext } from "react";
const AuthApi = createContext();
export default AuthApi;
Then define the context app.jsx
import React, from 'react'
import { AllRoutes } from 'routes/Routes';
import { BrowserRouter as Router } from "react-router-dom";
import AuthApi from 'store/AuthApi';
const App = () => {
const [user, setUser] = useState(false);
useEffect(() => {
// you can get user from localStorage or Cookie(js-cookie npm)
//then you can change user state true or false
}, [])
return (
<>
<AuthApi.Provider value={{ user, setUser }}>
<Router>
<AllRoutes />
</Router>
</AuthApi.Provider>
<Toast />
</>
)
}
export default App
then see AllRoutes
//routes/Routes
import React, { useContext } from "react";
import { Routes, Route } from "react-router-dom";
import { SignIn, SignUp, Dashboard } from "pages";
import AuthApi from "store/AuthApi";
export const ProtectedRouting = () => {
return (
<Routes >
<Route path='/' exact element={<Dashboard />} />
// add more protected routes
</Routes>
)
}
export const AuthRouting = () => {
return (
<Routes >
<Route exact={true} path='/sign-in' element={<SignIn />} />
<Route exact={true} path='/sign-up' element={<SignUp />} />
</Routes>
)
}
export const AllRoutes = ()=> {
const context = useContext(AuthApi);
console.log(context.user)
return (
context.user ?
<ProtectedRouting />
: <AuthRouting />
)
}
pages/SignIn.jsx
import React,{ useContext } from 'react';
import AuthApi from "store/AuthApi";
const SignIn = () => {
const context = useContext(AuthApi);
const signInSubmit =(e)=> {
e.preventDefault();
//post request to signin
// if login is successfull then save user or token in cookie or localStorage or something
context?.setUser(true);
//...
}
return (
//signin code here
<form onSubmit={signInSubmit}>
///input here
</form>
)
}
export default SignIn

React functional components not rendering in App.js

I am using only functional components in React so I can get a better grip on hooks.
But I am having trouble rendering my functional components in the App.js.
Why will only the ‘Login’ component/path render in the browser? None of the others. Please help me discover what is wrong with my App.js. Thank you!
App.js (I have commented out the hook/removed the prop, to simplify it)
import { React, useState } from 'react';
import './App.css';
import { Route } from 'react-router-dom';
import Home from './components/Home'
import Login from './components/Login'
import Signup from './components/Signup';
console.log('app loading')
function App() {
// const [user, setUser] = useState(props.user)
// console.log(props.user)
return (
<div className="App">
{/* <h1>This is app.js</h1> */}
<Route
exact path = "/"
compotent={Home}
/>
<Route
exact path="/login"
component={Login}
/>
<Route
exact path = "/signup"
compotent={Signup}
/>
</div>
);
}
export default App;
Home.js
import React from 'react'
console.log('home loading')
export default function Home() {
console.log('home function')
return (
<div>
<h1>This is home.js</h1>
</div>
)
}
Login.js (this is the only one that renders)
import React from 'react'
import { Link } from 'react-router-dom'
console.log('login loading')
export default function Login() {
console.log('login function loading')
return (
<div>
<h1>Login.js</h1>
<Link to="/auth/google">Login With Google</Link>
</div>
)
}
Signup.js
import React from 'react'
export default function Signup() {
console.log('signup function loading')
return (
<div>
<h1>This is Signup.js</h1>
</div>
)
}
Try to remove spaces exact path = "/" => exact path="/" for both Home and Signup routes
Try this:
import { React, useState } from 'react';
import './App.css';
import { Route, BrowserRouter as Router } from 'react-router-dom'
import Home from './components/Home'
import Login from './components/Login'
import Signup from './components/Signup';
console.log('app loading')
function App() {
// const [user, setUser] = useState(props.user)
// console.log(props.user)
return (
<div className="App">
{/* <h1>This is app.js</h1> */}
<Router>
<Route
exact path = "/"
compotent={Home}
/>
<Route
exact path="/login"
component={Login}
/>
<Route
exact path = "/signup"
compotent={Signup}
/>
</Router>
</div>
);
}
export default App;
This should work
Please restructure your app.jsx with the below changes:
import { React, useState } from 'react';
import './App.css';
import { Route, BrowserRouter as Router } from 'react-router-dom'; //I MADE CHANGE HERE
import Home from './components/Home'
import Login from './components/Login'
import Signup from './components/Signup';
function App() {
console.log('app loading')
return (
<div className="App">
<Router> //I MADE CHANGE HERE
<Route
exact path = "/"
compotent={Home}
/>
<Route
exact path="/login"
component={Login}
/>
<Route
exact path = "/signup"
compotent={Signup}
/>
</Router> //I MADE CHANGE HERE
</div>
);
}
export default App;
I had a spelling mistake in the '/' and '/signup' routes.
I had written 'compo*t*ent=...' instead of 'compo**n**ent'.
The code is now corrected and the compo**n**ents are rendering just find.

react slide out menu state = not setting state?

I'm trying to develop a slide-out menu with routing function for React. for some reason state = {} isn't setting defining sideDrawOpen what could the reasons for this be thanks for your help. the error I get running yarn start is
"Failed to compile.
./src/App.js
Line 21:45: 'sideDrawerOpen' is not defined no-undef
Search for the keywords to learn more about each error."
import React, { Component } from 'react';
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
import main_page from './components/main_page';
import setup_page from './components/setup_page';
import settings_page from './components/settings_page';
import Error from './components/Error';
import Nav from './components/Navigation/Nav';
import SideDrawer from './components/Navigation/SideDrawer';
import Backdrop from './components/Navigation/Backdrop';
export class App extends Component {
state = {
sideDrawerOpen: false
}
drawerToggleClickHandler = () => {
this.setState((prevState) =>{
return {sideDrawerOpen: !prevState,sideDrawerOpen};
});
};
render() {
let sideDrawer;
let backdrop;
if (this.state.sideDrawerOpen) {
sideDrawer = <SideDrawer />
backdrop = <Backdrop />
}
return (
<div className="App_margin">
<Router>
<div className='App'>
{sideDrawer}
{backdrop}
<Nav />
<Switch>
<Route path='/' component={setup_page} exact/>
<Route path='/main_page' component={main_page} />
<Route path='/settings_page' component={settings_page} />
<Route component={Error} />
</Switch>
</div>
</Router>
</div>
);
}
}
!prevState,sideDrawerOpen has a comma, not a .

I have two different headers because of Router

So the problem is that I'm new to REACT, I used create-react-app and added a Router function to route between components. Now I created a header which everything was okay with, but I added a hamburger-menu so I could route between my pages and suddenly my Header just got itself duplicated on my webpage.
App.js:
import React, {Component} from 'react';
import { BrowserRouter as Router, Route} from "react-router-dom";
import './App.css';
import './Header.css'
import SideDrawer from "./SideDrawer";
import Header from './Header'
import Backdrop from './Backdrop'
import Home from "./Home";
import LoginPage from "./LoginPage";
import SignupPage from "./SignupPage";
import RegisterEventPage from "./RegisterEventPage";
class App extends Component {
state = {
sideDrawerOpen: false
};
drawerToggleClickHandler = () => {
this.setState((prevState) => {
return {sideDrawerOpen: !prevState.sideDrawerOpen};
});
};
backDropClickHandler = () => {
this.setState({sideDrawerOpen: false});
};
render() {
let sideDrawer;
let backdrop;
if (this.state.sideDrawerOpen) {
sideDrawer = <SideDrawer/>;
backdrop = <Backdrop click={this.backDropClickHandler}/>;
}
return (
<div style={{height: '100%'}}>
<Header drawerClickHandler={this.drawerToggleClickHandler}/>
{sideDrawer}
{backdrop}
<Router>
<Route exact path="/" component={Home}/>
<Route path="/loginPage" component={LoginPage}/>
<Route path="/SignupPage" component={SignupPage}/>
<Route path="/RegisterEventPage" component={RegisterEventPage}/>
</Router>
</div>
);
}
}
export default App;
Header.jsx:
import React, {Component} from 'react';
import DrawerToggleButton from './DrawerToggleButton';
import './Header.css';
class Header extends Component {
render() {
return (
<header className="main_toolbar">
<nav className="toolbar_navigation">
<div>
<DrawerToggleButton click={this.props.drawerClickHandler}/>
</div>
<div className="toolbar_logo">IceBreaker</div>
<div className="spacer"></div>
</nav>
</header>
);
}
}
export default Header;
So if I for example remove from App.js my second header suddenly disappears.
Image of two headers
Render your header inside the router:
I also recomend you to use a switch in your router
You will need to import it :
import { BrowserRouter as Router, Route} from "react-router-dom";
return (
<div style={{height: '100%'}}>
<Router>
<Header drawerClickHandler={this.drawerToggleClickHandler}/>
{sideDrawer}
{backdrop}
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/loginPage" component={LoginPage}/>
<Route path="/SignupPage" component={SignupPage}/>
<Route path="/RegisterEventPage" component={RegisterEventPage}/>
</Switch>
</Router>
</div>
);

Routing in Meteor with React & React-Router

I want to make a second private page like links in MeteorJS with react, called landing, create the Landing.js component and import it into the routes file but at the time of going to the route in the browser "http: // localhost: 3000/landing "sends me to the NotFound page, which may be wrong? I would be grateful for the help
'../imports/routes/routes';
import React from 'react';
import Meteor from 'meteor/meteor';
import { Router, Route, browserHistory } from 'react-router';
import Vitae from '../ui/Vitae';
import Logeo from '../ui/Logeo';
import Registro from '../ui/Registro';
import NoEncontrado from '../ui/NoEncontrado';
import Landing from '../ui/Landing';
// flecha tracker
Tracker.autorun(() => {
const paginasUnautenticadas = ['/', '/registro'];
const paginasAutenticadas = ['/vitae', '/landing'];
const enPaginaPublica = () => {
if(Meteor.userId()) {
browserHistory.replace('/vitae');
}
};
const enPaginaPrivada = () => {
if(!Meteor.userId()) {
browserHistory.replace('/');
}
};
export const cambioAutenticacion = (estaAutenticado) => {
const pathname = browserHistory.getCurrentLocation().pathname;
const esPaginaUnautenticada = paginasUnautenticadas.includes(pathname);
const esPaginaAutenticada = paginasAutenticadas.includes(pathname);
if(esPaginaUnautenticada && estaAutenticado) {
browserHistory.replace('/vitae');
} else if (esPaginaAutenticada && !estaAutenticado) {
browserHistory.replace('/');
}
};
export const routes = (
<Router history={browserHistory}>
<Route path="/" component={Logeo}/>
<Route path="/vitae" component={Vitae}/>
<Route path="/registro" component={Registro}/>
<Route path="*" component={NoEncontrado}/>
<Route path="/landing" component={Landing}/>
</Router>
);
});
and my component Landing.js
import React from 'react';
export default class Landing extends React.Component {
render() {
return(
<div>
<h3>Landing Page</h3>
</div>
);
};
}
You have your Landing route after your wildcard "Not Found" route
<Route path="*" component={NoEncontrado}/>
<Route path="/landing" component={Landing}/>
I'm pretty sure that if you switch these two over, it will work as expected :)
<Route path="/landing" component={Landing}/>
<Route path="*" component={NoEncontrado}/>

Categories