reactJs App js - passing incoming data as props - reactjs

How do I pass data from the app.js file as json to the app.js file as props. I want to display the incoming data as json in the whole project.
I want to pass the incoming data as props.
{id: 1, first_name: "", last_name: "", profile: {…}}
{id: 1, userKey: "0245abb9-2837-4f37-ae02-9be1b88887ef", gsmNo: "05442221111", phone: ""}
Thank you from now
import React, { Component } from 'react';
import {BrowserRouter, Route, Switch } from 'react-router-dom';
// import { renderRoutes } from 'react-router-config';
import './App.scss';
import {updateCustomer} from "../components/helpers/actions/customerActions";
import { connect } from "react-redux";
const loading = () => <div className="animated fadeIn pt-3 text-center">Loading...</div>;
// Containers
const DefaultLayout = React.lazy(() => import('../containers/DefaultLayout'));
// Pages
const Login = React.lazy(() => import('../views/Pages/Login'));
const Register = React.lazy(() => import('../views/Pages/Register'));
const Page404 = React.lazy(() => import('../views/Pages/Page404'));
const Page500 = React.lazy(() => import('../views/Pages/Page500'));
class App extends Component {
// eslint-disable-next-line no-useless-constructor
constructor(props) {
super(props);
this.state = {
profile_items: [ ]
}
}
componentDidMount() {
this.props.onUpdateCustomer({ID: "-1", customerKey: "-1"});
console.log("app.js");
return fetch('http://127.0.0.1:8000/api/account/me',
{
headers: {
Authorization: `Bearer ${localStorage.getItem("id_token")}`,
"Content-Type": "application/json"
},
})
.then((response) => response.json() )
.then((responseData) => {
console.log(responseData);
this.setState({
profile_items: responseData
});
//console.log(this.state.profile_items)
return responseData;
})
.catch(error => console.warn(error));
}
render() {
return (
<BrowserRouter>
<React.Suspense fallback={loading()}>
<Switch >
<Route exact path="/login" name="Login Page" render={props => <Login {...props}/>} />
<Route exact path="/register" name="Register Page" render={props => <Register {...props}/>} />
<Route exact path="/404" name="Page 404" render={props => <Page404 {...props}/>} />
<Route exact path="/500" name="Page 500" render={props => <Page500 {...props}/>} />
<Route path="/" name="Home" render={props => <DefaultLayout {...props}/>} />
</Switch>
</React.Suspense>
</BrowserRouter>
);
}
}
const mapStateToProps = (state, props) => {
return state;
};
const mapDispatchToProps = {
onUpdateCustomer: updateCustomer,
};
export default connect(mapStateToProps, mapDispatchToProps) (App );

You can use HOC to pass props into Lazy Component. With my option, I think it work.
Create HOC:
const LazyHOC = ({ component: Component, ...rest }) => (
<Component {...rest} />
)
import your component:
const ComponentExample = React.lazy(() => import('./components/ComponentExample'));
Wrap Component with HOC:
const LazyComponentExample = props => <LazyHOC component={ComponentExample} {...props}/>
And you can pass props like this:
<React.Suspense fallback={loading()}>
<Switch >
<Route
exact path="/login"
name="Component example"
render={<LazyComponentExample props={...} />} />
</Switch>
</React.Suspense>

Related

ReactJS - component does not load with url parameter

Component does not load when I manually enter a url with parameter in the browser's search bar and naturally it says 'not working' in the console but when I click on a button going to '/:username' url from my index page, I don't get any error, it works pretty well. Where am I wrong?
router.js
const Main = () => (
<Switch>
<Route exact path="/login" component={FrontLogin} />
<Route path="/register" component={FrontRegister} />
<IndexRoute exact path="/home" component={FrontHome} />
<IndexRoute exact path="/:username" component={FrontProfile} />
<Redirect to="/home" />
</Switch>
)
index.js
class Index extends Component{
render(){
return(
<Provider {...Store}>
<BrowserRouter>
<Route component= {Main}/>
</BrowserRouter>
</Provider>
)
}
}
ReactDOM.render(<Index/>,document.getElementById('index'))
profile.index.js
const Profile = (props) => {
const {params} = props.match;
const [data, setData] = useState({});
const history = useHistory();
const [refresh, setRefresh] = useState(false);
console.log(props);
if(!props.location.key){
console.log('not working');
}
if (props.location.key) {
useEffect(() => {
axios
.get(
`/api/${params.username}`,
{
headers: {
Authorization:
"Bearer " +
props.AuthStore.appState.user.access_token,
},
}
)
.then((res) => {
if (res.data.username) {
setData(res.data);
setRefresh(true);
}
})
.catch((error) => {
console.log(error);
});
}, [refresh]);
}
console.log(refresh);
ProvideRoute.js
const PrivateRoute = ({
component:Component,
path,
...rest
}) => (
<Route path= {path} {...rest}
render={
props => isLoggedIn ? (
<Component {...props}/>
) : (
<Redirect to={{
pathname:"/login",
state:{
prevLocation:path,
error:'Giriş yapmalısın.'
}
}}/>
)
} />
)
export default withRouter(PrivateRoute);

Lazy loaded React router routes loading anyway

I've been trying to lazy load routes in React using React.lazy and Suspense. But some components are loading regardless of the current route, exactly: Feed, Profile and Settings.
Notice I don't actually want to lazy load Components like MenuAppBar and SnackAlert but if I import them normally and remove their Suspense, code-splitting straight doesn't even work and everything loads and the whole app is just a single chunk.
import {createMuiTheme, MuiThemeProvider} from "#material-ui/core";
import {yellow} from "#material-ui/core/colors";
import CssBaseline from "#material-ui/core/CssBaseline";
import axios from "axios";
import React, {lazy, Suspense, useEffect, useState} from "react";
import {BrowserRouter as Router, Route, Switch} from "react-router-dom";
import "./css/feed.css";
import "./css/style.css";
const Feed = lazy(() => import("./routes/Feed"));
const Profile = lazy(() => import("./routes/Profile"));
const Home = lazy(() => import("./routes/Home"));
const Settings = lazy(() => import("./routes/Settings"));
const NotFound = lazy(() => import("./routes/NotFound"));
const MenuAppBar = lazy(() => import("./components/MenuAppBar"));
const SnackAlert = lazy(() => import("./components/SnackAlert"));
const App: React.FC = () => {
const [isLogged, setIsLogged] = useState(localStorage.getItem("token") ? true : false);
const [user, setUser] = useState<User>(
isLogged ? JSON.parse(localStorage.getItem("userInfo") as string) : {admin: false}
);
const [openError, setOpenError] = useState<boolean>(false);
const [errorMsg, setErrorMsg] = useState<string>("");
const [severity, setSeverity] = useState<Severity>(undefined);
const [pwa, setPwa] = useState<any>(null);
const [showBtn, setShowBtn] = useState<boolean>(false);
const [isLight, setIsLight] = useState<boolean>(
(JSON.parse(localStorage.getItem("theme") as string) as boolean) ? true : false
);
const theme: customTheme = {
darkTheme: {
palette: {
type: "dark",
primary: {
main: yellow[600]
}
}
},
lightTheme: {
palette: {
type: "light",
primary: {
main: yellow[700]
}
}
}
};
window.addEventListener("beforeinstallprompt", (event) => {
event.preventDefault();
setPwa(event);
setShowBtn(true);
});
window.addEventListener("appinstalled", (e) => {
setShowBtn(false);
setErrorMsg("App installed!");
setSeverity("success");
setOpenError(true);
});
const handleClick = () => {
if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
setErrorMsg(`Please, open the share menu and select "Add to Home Screen"`);
setSeverity("info");
setOpenError(true);
} else {
if (pwa) {
pwa.prompt();
pwa.userChoice.then((choiceResult: {outcome: "accepted" | "refused"}) => {
if (choiceResult.outcome === "accepted") {
setErrorMsg("App downloading in the background..");
setSeverity("info");
setOpenError(true);
}
setPwa(null);
});
}
}
};
useEffect(() => {
const token: string | null = localStorage.getItem("token");
let userInfo: User = JSON.parse(localStorage.getItem("userInfo") as string);
if (userInfo && token && !userInfo.admin) {
setUser(userInfo);
setIsLogged(true);
}
if (isLogged) {
axios
.get("/api/auth/user", {
headers: {
"x-auth-token": `${token}`
}
})
.then((res) => {
if (!userInfo || !token) {
setUser(res.data as User);
}
localStorage.setItem(`userInfo`, JSON.stringify(res.data as User));
setIsLogged(true);
})
.catch((err) => {
if (err) {
setIsLogged(false);
}
});
} else {
localStorage.removeItem("token");
localStorage.removeItem("userInfo");
}
}, [isLogged]);
return (
<MuiThemeProvider theme={isLight ? createMuiTheme(theme.lightTheme) : createMuiTheme(theme.darkTheme)}>
<CssBaseline />
<Router>
<Suspense fallback={<div></div>}>
<Route
path="/"
render={() => (
<>
<MenuAppBar
isLogged={isLogged}
setIsLogged={setIsLogged}
user={user}
setUser={setUser}
isLight={isLight}
setIsLight={setIsLight}
/>
<SnackAlert severity={severity} errorMsg={errorMsg} setOpenError={setOpenError} openError={openError} />
</>
)}
/>
</Suspense>
<Suspense fallback={<div></div>}>
<Switch>
<Route exact path="/" render={() => <Home />} />
<Route exact path="/profile/:id" render={() => <Profile />} />
<Route exact path="/feed" render={() => <Feed isLogged={isLogged} user={user} />} />
<Route
exact
path="/settings"
render={() => (
<Settings isLight={isLight} setIsLight={setIsLight} handleClick={handleClick} showBtn={showBtn} />
)}
/>
<Route render={() => <NotFound />} />
</Switch>
</Suspense>
</Router>
</MuiThemeProvider>
);
};
export default App;
You are wrapping your entire Switch in a single Suspense, so all components will be lazily loaded at the same time. You probably only want each to be fetched/loaded when the specific route is rendered the first time.
<Switch>
<Route
exact
path="/"
render={props => (
<Suspense fallback={<div>Loading...<div>}>
<Home {...props} />
</Suspense>
)}
/>
<Route
exact
path="/profile/:id"
render={props => (
<Suspense fallback={<div>Loading...<div>}>
<Profile {...props} />
</Suspense>
)}
/>
<Route
exact
path="/feed"
render={() => (
<Suspense fallback={<div>Loading...<div>}>
<Feed isLogged={isLogged} user={user} {...props} />
</Suspense>
)}
/>
<Route
exact
path="/settings"
render={() => (
<Suspense fallback={<div>Loading...<div>}>
<Settings
isLight={isLight}
setIsLight={setIsLight}
handleClick={handleClick}
showBtn={showBtn}
{...props}
/>
</Suspense>
)}
/>
<Route
render={() => <NotFound />}
/>
</Switch>
There is a lot of repetition here, so it is practical to factor out the suspense into a HOC.
const withSuspense = (WrappedComponent, fallback) => props => (
<Suspense fallback={fallback}>
<WrappedComponent {...props} />
</Suspense>
);
You can either decorate each perspective default export, i.e.
export default withSuspense(Home, <div>Loading...<div>);
App.js
...
<Switch>
<Route exact path="/" render={props => <Home {...props} />} />
or decorate them in your App
const HomeWithSuspense = withSuspense(Home, <div>Loading...<div>);
...
<Switch>
<Route
exact
path="/"
render={props => <HomeWithSuspense {...props} />}
/>
...
</Switch>
In case someone is having the same problem, the actual problem was that some of the components had other components within them which weren't exported as default and that's why they weren't being lazy-loaded.
So if you're having the same problem, you should check the import tree of the component you're trying to lazy-load and make sure every component in this tree is exported as default.
For more information refer to the named exports section in the react docs.
Thanks everyone for your help!
That should work, I would look other problems, like build scripts, or some other piece of code using those same bundles. (e.g. the inheritance thing you mentioned in comments)
Please try this once if above are worked
import React, { Suspense, lazy } from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
const Home = lazy(() => import("./components/Home"));
const About = lazy(() => import("./components/About"));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route exact path='/' element={<Home/>}/>
<Route exact path='/about' element={<About/>}/>
</Routes>
</Suspense>
</Router>
);
export default App
There's no need for the whole tree that you're trying to lazy load to have default imports and exports. The component tree with its unique dependencies will be bundled into lazy chunk by default.
For eg.
Component.js
import { x, y } from z
.....
export default Component
main.js
const Component = React.lazy(() => import('Component.js')
Here the main.js chunk will not include code any code from z or
any of the code from Component.js and its unique dependencies
https://webpack.js.org/guides/code-splitting/#dynamic-imports
https://create-react-app.dev/docs/code-splitting/#appjs

How to restrict access to routes in react-router-dom based on session?

I have a React front-end and Python back-end with user session management using flask-login's HttpOnly Session Cookies. How can I restrict react-router-dom routes based on this type of session management? I've created a ProtectedRoute component:
import { Route, Redirect } from 'react-router-dom';
class ProtectedRoute extends Component {
constructor(props) {
super(props);
this.state = {
authenticated: false,
}
}
render() {
const { component: Component, ...props } = this.props
return (
<Route
{...props}
render={props => (
this.state.authenticated ?
<Component {...props} /> :
<Redirect to='/login' />
)}
/>
)
}
}
export default ProtectedRoute;
Is it possible to set this.setState({authenticated: true}) based on the existing session?
Why not pass authenticated (or isEnabledin my example) as a prop? ProtectedRoute will rerender when its props change. This is what I use in my React applications:
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
const ProtectedRoute = ({isEnabled, ...props}) => {
return (isEnabled) ? <Route {...props} /> : <Redirect to="/login"/>;
};
export default ProtectedRoute;
And then you can just use this like so:
<ProtectedRoute path="/dashboard" isEnabled={isAuthenticated()} />
I know this question is old but I was looking for the same thing. Here's my routes.js file:
import auth from './services/auth'
const PrivateRoute = ({isAuthenticated, ...props}) => {
return (isAuthenticated) ? <Route {...props} /> : <Redirect to="/login"/>;
};
class Routes extends React.Component {
constructor(){
super();
this.state = {
isAuthenticated: false
}
}
componentDidMount(){
auth.get('')
.then( async (response) => {
const status = await response.status
if (status === 200) {
this.setState({isAuthenticated: true})
} else {
this.setState({isAuthenticated: false})
}
})
.catch( async (error) => console.log(error))
}
render() {
return (
<BrowserRouter>
<Switch>
<Route path="/login" exact component={Login} />
<PrivateRoute isAuthenticated={this.state.isAuthenticated} path="/" component={() => "barra"}/>
<PrivateRoute isAuthenticated={this.state.isAuthenticated} path="/home" component={() => "home"}/>
<PrivateRoute isAuthenticated={this.state.isAuthenticated} path="/profile" component={() => "profile"}/>
</Switch>
</BrowserRouter>
)
};
}
And auth import is:
const axios = require('axios');
axios.defaults.withCredentials = true;
const auth = axios.create({
baseURL: "http://localhost:5000/auth"
})
export default auth;
So, basically I have a Flask app with Flask-Login running on another local server (with CORS enabled THIS IS VERY IMPORTANT) and if 200 is returned, user on react is authenticated.

react router "# sign inside route"

i using react-router for my project,
in that there's a problem which is for every route "#" sign is added at the start of every router path..
ex": http://localhost:3000/#/login
i want to remove that # sign but i couldn't able solve it my self.
procedure of my routing is
in app.js im checking the user is signed in or not if not signed in then he will redirect into /login page.(for that also it is showing path as http://localhost:3000/#/login)
below is the app.js
import React, { Component, Fragment } from "react";
import { HashRouter, Route, Switch, Redirect } from "react-router-dom";
// import { renderRoutes } from 'react-router-config';
import "./App.scss";
import { connect } from "react-redux";
import { loadUser } from "./actions/authActions";
const loading = () => (
<div className="animated fadeIn pt-3 text-center">Loading....</div>
);
// Containers
const DefaultLayout = React.lazy(() =>
import("./containers/DefaultLayout/DefaultLayout")
);
// Pages
const Login = React.lazy(() => import("./views/Login/Login"));
const Register = React.lazy(() => import("./views/Register/Register"));
const Page404 = React.lazy(() => import("./views/Page404/Page404"));
const Page500 = React.lazy(() => import("./views/Page500/Page500"));
class App extends Component {
componentDidMount() {
this.props.LOADUSER();
}
render() {
return (
<HashRouter>
<React.Suspense fallback={loading()}>
<Switch>
{!this.props.isAuthenicated ? (
<Fragment>
<Redirect from="*" to="/login" />
<Route
exact
path="/login"
name="Login Page"
render={props => <Login {...props} />}
/>
{/* <Route
exact
path="/register"
name="Register Page"
render={(props) => <Register {...props} />}
/>
<Route
exact
path="/404"
name="Page 404"
render={(props) => <Page404 {...props} />}
/>
<Route
exact
path="/500"
name="Page 500"
render={(props) => <Page500 {...props} />}
/> */}
</Fragment>
) : (
<Route
name="Home"
path="/"
render={props => <DefaultLayout {...props} />}
/>
)}
</Switch>
</React.Suspense>
</HashRouter>
);
}
}
const mapStateToProps = state => ({
isAuthenicated: state.auth.isAuthenicated,
isLoading: state.auth.isLoading,
error: state.error,
token: state.auth.token
});
const mapDispachToProps = dispach => {
return {
//LOGIN: (newUser) => dispach(login(newUser)),
LOADUSER: () => dispach(loadUser())
};
};
export default connect(mapStateToProps, mapDispachToProps)(App);
else he is signed in then im using a component called DefaultLayout Component I will render it.
it has all the routes for other usages which is using routes from routes.js.
below is the DefaultLayout Component
import React, { Component, Suspense } from "react";
import { Redirect, Route, Switch } from "react-router-dom";
import * as router from "react-router-dom";
import { Container } from "reactstrap";
import { logout } from "../../actions/authActions";
import { ToastContainer } from "react-toastify";
import Loader from "react-loaders";
import "react-toastify/dist/ReactToastify.css";
import {
AppHeader,
AppSidebar,
AppSidebarFooter,
AppSidebarForm,
AppSidebarHeader,
AppSidebarMinimizer,
AppBreadcrumb2 as AppBreadcrumb,
AppSidebarNav2 as AppSidebarNav
} from "#coreui/react";
// sidebar nav config
import _navs from "../../_nav";
// routes config
import routes from "../../routes";
import { connect } from "react-redux";
const DefaultHeader = React.lazy(() => import("./DefaultHeader"));
class DefaultLayout extends Component {
state = {
isAuthenicated: true
};
loading = () => <Loader type="ball-triangle-path" />;
signOut(e) {
e.preventDefault();
this.props.history.push("/login");
this.props.LOGOUT();
}
render() {
return (
<div className="app">
<AppHeader fixed>
<Suspense fallback={this.loading()}>
<DefaultHeader onLogout={e => this.signOut(e)} />
</Suspense>
</AppHeader>
<div className="app-body">
<AppSidebar fixed display="lg">
<AppSidebarHeader />
<AppSidebarForm />
<Suspense>
<AppSidebarNav
navConfig={_navs}
{...this.props}
router={router}
/>
</Suspense>
<AppSidebarFooter />
<AppSidebarMinimizer />
</AppSidebar>
<main className="main">
<AppBreadcrumb appRoutes={routes} router={router} />
<Container fluid>
<Suspense fallback={this.loading()}>
<Switch>
{routes.map((route, idx) => {
return route.component ? (
<Route
key={idx}
path={route.path}
exact={route.exact}
name={route.name}
render={props => (
<route.component {...props} {...route.props} />
)}
/>
) : null;
// (
// <Redirect from="*" to="/dashboard" />
// );
})}
<Redirect from="*" to="/" />
</Switch>
</Suspense>
<ToastContainer autoClose={3000} position="bottom-center" />
</Container>
</main>
</div>
</div>
);
}
}
const mapStateToProps = state => ({
isAuthenicated: state.auth.isAuthenicated,
error: state.error
});
const mapDispachToProps = dispach => {
return {
LOGOUT: () => dispach(logout())
};
};
export default connect(mapStateToProps, mapDispachToProps)(DefaultLayout);
example of routes.js also below
const routes =[{
path: "/",
exact: true,
name: "Home",
component: Dashboard
},
{
path: "/user_overview",
name: "Users Overview",
component: Register
}]
for every route it's showing # can anyone help me to resolve that # sign in the route path?
Thank you!
You are using HashRouter this is the purpose of this Router.
Usually one uses it in-order to prevent the server to get those routes.
If you want to use real routes just replace it with BrowserRouter.
Pay attention that your server will need to be able to support those routes.
navigate to some route say /some/page press reload, make sure that your server return your client code.

React Router/WithRouter not redirecting even with WithRoute

I have a simple enough react app. I have two buttons/actions that redirect. sign out and add. signout is working but add is not.
before add click
history.location '/'
location '/'
after add click
history.location '/add'
location '/add'
but related component doesnt render.
router.js
let appHistory = createHistory();
const appRouter = () => (
<Router history={appHistory}>
<Switch>
<Route path="/signin" component={SignInUp} exact={true} />
<Route path="/" component={Landing} />
<Route path="/add" component={CreateEvent} />
<Route path="/eventview" component={EventDetails} />
</Switch>
</Router>
)
Main component
import React, {Component} from 'react';
import RequireAuth from './RequireAuth';
import {startSignOut} from '../actions/auth';
import {fetchEvents} from '../actions/event';
import {connect} from 'react-redux';
import {withRouter} from 'react-router';
import EventItem from './EventItem';
import Header from './Header';
const EventDisplay = class EventDisplay extends Component {
componentDidMount = () => {
this.props.fetchEvents();
}
handleAddEvent = () => {
console.log(this.props);
this.props.history.push('/add');
}
handleSignOut = () => {
this.props.startSignOut();
}
render() {
return (
<div>
<Header signOut={this.handleSignOut}/>
{
this.props.events.map((event, ind) => {
return <EventItem key={ind} history={this.props.history} index={ind + 1} event={event}/>
})
}
<button onClick={() => this.handleAddEvent()}>+</button>
</div>
)
}
}
const mapDispatchToProps = (dispatch) => ({
startSignOut: () => startSignOut(dispatch),
fetchEvents: (userId) => dispatch(fetchEvents(userId))
});
const mapStateToProps = (state) => ({
events: state.events
})
const connectedWithRouter = withRouter(connect(mapStateToProps, mapDispatchToProps)(RequireAuth(EventDisplay)));
export default connectedWithRouter;
Header.js
const Header = (props) => {
return (
<div>
<h2>Eventio</h2>
<span>circle</span>
<span>user</span>
<button onClick={() => props.signOut()}>Sign out</button>
</div>
)
}
export default Header;
Your Route with path / will be used for any path that is not /signin. Give it an exact prop and it will only be used for path /.
const appRouter = () => (
<Router history={appHistory}>
<Switch>
<Route exact path="/" component={Landing} />
<Route path="/signin" component={SignInUp} />
<Route path="/add" component={CreateEvent} />
<Route path="/eventview" component={EventDetails} />
</Switch>
</Router>
)

Resources