hi react admin community,
I want to use logout button with custom component and router. I have checked documentation but not found any solution.
please suggest to me how I can use it.
below I added my code.
Adminroot Component
This is Admin Component.
import React from 'react';
import { Admin, Resource } from 'react-admin';
import jsonServerProvider from 'ra-data-json-server';
import { UserList } from "../users/users";
import Dashboard from './dashboard';
import MyLogoutButton from '../auth/logout';
const authProvider = {
logout: params => Promise.resolve(),
};
function Adminroot(props) {
const dataProvider = jsonServerProvider('http://jsonplaceholder.typicode.com');
return (
<div>
<Admin logoutButton={MyLogoutButton} loginPage={false} dashboard={Dashboard} dataProvider={dataProvider}>
<Resource name="users" list={UserList} />
</Admin>
</div>
);
}
export default Adminroot;
MyLogoutButton Component
This component contains default code which provides react-admin for logout.
Now, when clicks on Logout button. by default redirects to /login Url.
There renders a Logout component (below written the logout component code) that contains logout logic and redirect to /signin but it shows blank page until I refresh the page.
import React, { forwardRef } from 'react';
import { useLogout } from 'react-admin';
import MenuItem from '#material-ui/core/MenuItem';
import ExitIcon from '#material-ui/icons/PowerSettingsNew';
const MyLogoutButton = forwardRef((props, ref) => {
const logout = useLogout();
const handleClick = () => logout();
return (
<MenuItem
onClick={handleClick}
ref={ref}
>
<ExitIcon /> Logout
</MenuItem>
);
});
export default MyLogoutButton;
Logout Component
import React , { useContext } from 'react';
import { AppContext } from '../../AppContext';
import { Redirect } from 'react-router-dom';
function Logout(props){
const {handleSignOut} = useContext(AppContext);
handleSignOut();
return props.history.push('/signin');
}
export default Logout;
Related
I tried to debug my code but I lost right now.
Basicly I created State that open Login window and overlay that are Portals, when someone click the login button. its works fine but my problem is that I want when someone click on the overlay that the login window and the overlay will close.
I can't achieve that unfortunately.
Thanks For Advance !
Here is the code :
App.js
import { useState } from "react";
import Home from "./components/Elements/Home";
import Footer from "./components/UI/Footer";
import NaviBar from "./components/UI/NaviBar";
import "./App.css";
import Auth from "./components/Auth/Auth";
function App(props) {
const [openWindow, setOpenWindow] = useState(false);
const clickImport = (data) => {
setOpenWindow(true);
};
const closeHandler = () => {
setOpenWindow(false);
};
return (
<>
<NaviBar dataClick={clickImport} />
{openWindow && <Auth dataClickClose={closeHandler} />}
<Home />
<Footer />
</>
);
}
export default App;
Auth.js
import { useState } from "react";
import ReactDOM from "react-dom";
import classes from "./Auth.module.css";
import Login from "./Login";
import Overlay from "./Overlay";
const Auth = (props) => {
return (
<>
{ReactDOM.createPortal(<Login />, document.getElementById("auth"))}
{ReactDOM.createPortal(
<Overlay onClick={props.dataClickClose} />,
document.getElementById("blur")
)}
</>
);
};
export default Auth;
Basicly I created State that open Login window and overlay that are Portals, when someone click the login button. its works fine but my problem is that I want when someone click on the overlay that the login window and the overlay will close.
Solved It.
I forgot to update the Overlay component.
here is my fix:
import classes from "./Overlay.module.css";
const Overlay = (props) => {
return <div className={classes.bgContainer} onClick={props.closeClick}></div>;
};
export default Overlay;
Im trying to use useContext hook to pass variables and functions through different components without lifting them to the main App.js component. I was trying to do this and it seemed to compile correctly but when i go to my browser my app is stucked in a blank page and remains loading.
LoginContext.js: In this component i store the user data in an object using the useState hook and i use jwt_decode to decode the use token and get all the data i need to store.
import React, { createContext, useState } from "react";
import jwt_decode from 'jwt-decode';
const LoginContext = createContext();
export function LoginProvider({children}) {
const [user, setUser] = useState({})
function handleCallbackResponse(response){
var userData = jwt_decode(response.credential); //Token with the login user Data
setUser(userData); //Store user Data
/* console.log(userData) */
document.getElementById('signInDiv').hidden = true;
}
function handleSignOut(event) {
setUser({}) //Empy the user Data
document.getElementById('signInDiv').hidden = false;
}
return(
<LoginProvider value={{user, handleCallbackResponse, handleSignOut}}>{children}</LoginProvider>
);
}
export default LoginContext
The i have my Login.js which uses LoginContext: Here i use the user to show the different data of the logged in use and the handleCallbackResponse to do my Login.
import React, { useContext, useEffect } from 'react'
import LoginContext from '../LoginContext';
const Login = () => {
const {user, handleCallbackResponse, handleSignOut} = useContext(LoginContext)
useEffect(()=>{
/*global google*/
google.accounts.id.initialize({
client_id:"My client ID",
callback: handleCallbackResponse
})
google.accounts.id.prompt();
google.accounts.id.renderButton(
document.getElementById('signInDiv'),
{theme: 'outline', size: 'medium'}
)
}, []);
return (
<div>
<div id="signInDiv"></div>
{
//If user objetc is not empty show sign out button
Object.keys(user).length !== 0 &&
<button onClick={(e)=>handleSignOut(e)}>Sign Out</button>
}
{user &&
<div>
<img src={user.picture} alt="" />
<h3>{user.name}</h3>
</div>
}
</div>
)
}
export default Login
App.js:
import './App.css';
import Login from './atoms/Login';
import { BrowserRouter , Routes, Route } from 'react-router-dom';
import Dashboard from './pages/Dashboard';
import { LoginProvider } from './LoginContext';
import PrivateRoutes from './utils/PrivateRoutes';
function App() {
return (
<LoginProvider>
<BrowserRouter>
<Routes>
{/* <Route element={<PrivateRoutes/>}>
</Route> */}
<Route exact path="/dashboard" element={<Dashboard/>}/>
<Route path="/" element={<Login/>} />
</Routes>
</BrowserRouter>
</LoginProvider>
);
}
export default App;
For some reason my application runs with no error but in the browser it remains loading with a blank page and im not able to inspect the page.
Instead of:
<LoginProvider value={{user, handleCallbackResponse, handleSignOut}}>{children}</LoginProvider>
);
Replace with
<LoginContext.Provider value={{user, handleCallbackResponse, handleSignOut}}>{children}</LoginContext.Provider>
I want to print url params(:uname ,:unumber) through Profile functional component. Here is my code.
My route in App.js
<Route path="/profile/:uname-:unumber" component={Profile} >
<Profile />
</Route>
I'm clicking profile url from Dashboard.js; this is my link
<Link to={{
pathname: `/profile/${userDetail.name}-${userDetail.u_number}`,
}} >view profile</Link>
on click on this link it is generating a url for eg: 'http://localhost:3000/profile-mynamehere-747484' and it is redirecting to profile component. But how to print to access the uname and unumber in profile component. I tried like this but not works
import React, {useState, useEffect, Component } from "react";
import axios from "axios";
import { useHistory,useParams } from "react-router-dom";
import Header from "../Header";
import {
BrowserRouter as Router,
Route,
Link,
Redirect,
withRouter
} from "react-router-dom";
const Profile = ({uname, unumber}) => {
console.log(uname); // here I want to print mynamehere from url, but not prints name
console.log(unumber);// here I want to print 747484 from url, but not prints unumber
return (
<div>
</div>
);
};
export default Profile;
use UseParams like this in profile component
const { uname,unumber } = useParams();
In Profile you should useParams to get pass the uname & unumber:
import { useHistory,useParams } from "react-router-dom";
const Profile = () => {
const {uname, unumber} = useParams()
console.log(uname);
console.log(unumber);
return (
<div>
</div>
);
};
In your profile component do the following:
import React, {useState, useEffect, Component } from "react";
import axios from "axios";
import { useHistory,useParams } from "react-router-dom";
import Header from "../Header";
const Profile = () => {
const {uname, unumber} = useParams()
console.log(uname-unumber)
return (
<div>
</div>
);
};
export default Profile;
I am using contextApi with nextjs and I'm having some trouble when providing a context just for certain routes. I am able to make the context available for just a few routes, but when I transition from one to the other through linking, I end up losing the state of my application.
I have three files inside my pages folder:
index.tsx,
Dashboard/index.tsx and
SignIn/index.tsx.
If I import the provider inside the files Dashboard/index.tsx and SignIn/index.tsx and go from one page to the other by pressing a Link component from next/link, the whole state is set back to the initial state.
The content of the Dashboard/index.tsx file
import React from 'react';
import Dashboard from '../../app/views/Dashboard';
import { AuthProvider } from '../../contexts/auth';
const Index: React.FC = () => (
<AuthProvider>
<Dashboard />
</AuthProvider>
);
export default Index;
This is the contend of the SignIn/index.tsx file:
import React from 'react';
import SignIn from '../../app/views/SignIn';
import { AuthProvider } from '../../contexts/auth';
const Index: React.FC = () => (
<AuthProvider>
<SignIn />
</AuthProvider>
);
export default Index;
The views folder is where I create the components that will be rendered.
The content of the file views/SignIn/index.tsx is:
import React, { useContext } from 'react';
import Link from 'next/link';
import { AuthContext } from '../../../contexts/auth';
const SignIn: React.FC = () => {
const { signed, signIn } = useContext(AuthContext);
async function handleSignIn() {
signIn();
}
return (
<div>
<Link href="Dashboard">Go back to Dashboard</Link>
<button onClick={handleSignIn}>Click me</button>
</div>
);
};
export default SignIn;
And the content of the file views/Dashboard/index.tsx is:
import React, { useContext } from 'react';
import Link from 'next/link';
import { AuthContext } from '../../../contexts/auth';
const Dashboard: React.FC = () => {
const { signed, signIn } = useContext(AuthContext);
async function handleSignIn() {
signIn();
}
return (
<div>
<Link href="SignIn">Go back to sign in page</Link>
<button onClick={handleSignIn}>Click me</button>
</div>
);
};
export default Dashboard;
I am able to access the context inside both /Dashboard and /SignIn, but when I press the link, the state comes back to the initial one. I figured out that the whole provider is rerenderized and therefore the new state becomes the initial state, but I wasn't able to go around this issue in a "best practices manner".
If I put the provider inside _app.tsx, I can maintain the state when transitioning between pages, but I end up providing this state to the / route as well, which I am trying to avoid.
I was able to go around this by doing the following, but it really does not seem to be the best solution for me.
I removed the Providers from Pages/SignIn/index.tsx and Pages/Dashboard/index.tsx and used the following snippet for the _app.tsx file:
import React from 'react';
import { AppProps } from 'next/app';
import { useRouter } from 'next/router';
import { AuthProvider } from '../contexts/auth';
const App: React.FC<AppProps> = ({ Component, pageProps }) => {
const router = useRouter();
const AuthProviderRoutes = ['/SignIn', '/Dashboard'];
return (
<>
{AuthProviderRoutes.includes(router.pathname) ? (
<AuthProvider>
<Component {...pageProps} />
</AuthProvider>
) : <Component {...pageProps} />}
</>
);
};
export default App;
Does anyone have a better solution?
I am using react along with redux and material-ui to make a component. I am attempting to write an export statement export default connect()(withRouter(FirstPage))(withStyles(styles)(FirstPage))
However, this doesn't seem to work I get an error that says
TypeError: Cannot set property 'props' of undefined
this.props = props;
This error is referencing one of my node_modules.
Here is my full code:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {withRouter} from 'react-router-dom'
import { withStyles } from '#material-ui/core/styles';
import Card from '#material-ui/core/Card';
import CardActions from '#material-ui/core/CardActions';
import CardContent from '#material-ui/core/CardContent';
import Button from '#material-ui/core/Button';
const styles = theme =>({
root: {
maxWidth: 345,
},
})
class FirstPage extends Component {
state = {
feeling: ''
}
//This function will dispatch the users response to index.js
//The dispatch type here is 'SET_FEELING'
submitData=(event) => {
event.preventDefault();
this.props.dispatch({type: 'SET_FEELING', payload: this.state})
this.changeLocation();
}
//This function will update the local state with the users response
handleChange= (event) => {
this.setState({
feeling: event.target.value
})
}
//This function will change the current url when a button is clicked
changeLocation= ()=> {
this.props.history.push('/secondPage')
}
render(){
const { classes } = this.props;
return(
<div>
<Card >
<CardContent className={classes.root}>
<form>
<input onChange={this.handleChange} placeholder='How are you feeling' value={this.state.feeling} />
</form>
</CardContent>
<CardActions>
<Button onClick={this.submitData}>Submit</Button>
</CardActions>
</Card>
</div>
)
}
}
//this export connects the component to the reduxStore as well as allowing us to use the history props
export default connect()(withRouter(FirstPage))(withStyles(styles)(FirstPage))
I believe the following code should work:
export default withRouter(connect()(withStyles(styles)(FirstPage)))
Instead of
export default connect()(withRouter(FirstPage))(withStyles(styles)(FirstPage))
First of all, connect() returns a function that only accepts an argument. Second, connect() should be wrapped inside withRouter(). This problem is stated in the github docs of React Router.
without using react-redux :
export default (withStyles(styles), withRouter)(FirstPage);