reactjs redux - user is null - javascript

I dont know why when i try to fetch data from api using redux (i can see the data in when i mapstatetoprops ) but this error (user is null ) message show up when i try to display data to user.
this is a screenshot shown the user is null error
I call the dispatch from componentDidMount react, i think its the right place to call api,
this is my code :
import React, { Component } from 'react';
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { connect } from 'react-redux';
import store from './state/store';
import { loadUser } from './state/actions/auth/authActions';
//pages
import Login from './app/auth/Login';
import Wrapper from './wrapper/Wrapper';
class App extends Component {
componentDidMount() {
store.dispatch(loadUser());
}
render() {
const { token, user, isLoading } = this.props.auth
return (
<Router>
<Routes>
<Route path='/login' element={<Login />} />
<Route path='/' element={token ? <Wrapper user={user._id} isLoading={isLoading}></Wrapper> : <Login />} />
</Routes>
</Router>
)
}
}
const mapStateToProps = state => {
return {
auth: state.auth
}
}
export default connect(mapStateToProps, { loadUser })(App);

Related

Why dashboard route is not accessible to me even if I am logged in?

I am using private route in my app to access dashboard. if I am not logged in it worked correctly and redirect me to the sign in page. but even if I am logged in it does not gives access to dashboard. Here is my code.
App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Home from './containers/Home';
import Login from './containers/Login';
import Dashboard from './containers/Dashboard';
import PrivateRoute from './components/PrivateRoute';
import { Provider } from 'react-redux';
import store from './store';
const App = () => (
<Provider store={store}>
<Router>
<Layout>
<Switch>
<Route exact path='/' component={Home} />
<PrivateRoute exact path='/dashboard' component={Dashboard} />
<Route exact path='/login' component={Login} />
</Switch>
</Layout>
</Router>
</Provider>
);
export default App;
PrivateRoute.js
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
const PrivateRoute = ({ component: Component, auth, ...rest }) => (
<Route
{...rest}
render={(props) => {
if (!auth.isAuthenticated) {
return <Redirect to="/login" />;
} else {
return <Component {...props} />;
}
}}
/>
);
const mapStateToProps = (state) => ({
auth: state.auth,
});
export default connect(mapStateToProps)(PrivateRoute);
And if I am logged in on react redux tool my states are these
I noticed even if isAuthanticated becomes true after login but else part of privateRoutes.js never called

React-Redux: Access dispatch type in JSX

I have a login system with React-Redux and I want to display JSX when a specific dispatch Type is send.
For example when the login system failed the dispatch type is LOGIN_FAIL and I want to display an error message but when the authentication is successful then the dispatch type is LOGIN_SUCCESS and I want to display a success message. I already access the username trough mapStateToProps but I was curious if there is another way trough the dispatch type to do conditional rendering?
Thanks for your advice or tips on that topic.
This is my actions.js:
export const login = (email, password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ email, password });
try {
const res = await axios.post(`${process.env.REACT_APP_API_URL}/auth/jwt/create/`, body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
dispatch(load_user());
} catch (err) {
dispatch({
type: LOGIN_FAIL
});
}
};
When i do user authentication, and i want to conditially render a component. I use React routing dom. This way i can create a PrivateRoute that will render the individual component out and redirect if the user !isAuthenticated. Check this out /
https://blog.bitsrc.io/build-a-login-auth-app-with-mern-stack-part-1-c405048e3669
This is the tutorial that you can clone the git
Private Route:
import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
const PrivateRoute = ({ component: Component, auth, ...rest }) => (
<Route
{...rest}
render={props =>
auth.isAuthenticated === true ? (
<Component {...props} />
) : (
<Redirect to="/login" />
)
}
/>
);
PrivateRoute.propTypes = {
auth: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth
});
export default connect(mapStateToProps)(PrivateRoute);
MAIN APP:
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import jwt_decode from "jwt-decode";
import setAuthToken from "./utils/setAuthToken";
import { setCurrentUser, logoutUser } from "./actions/authActions";
import { Provider } from "react-redux";
import store from "./store";
import Navbar from "./components/layout/Navbar";
import Landing from "./components/layout/Landing";
import Register from "./components/auth/Register";
import Login from "./components/auth/Login";
import PrivateRoute from "./components/private-route/PrivateRoute";
import Dashboard from "./components/dashboard/Dashboard";
import "./App.css";
// Check for token to keep user logged in
if (localStorage.jwtToken) {
// Set auth token header auth
const token = localStorage.jwtToken;
setAuthToken(token);
// Decode token and get user info and exp
const decoded = jwt_decode(token);
// Set user and isAuthenticated
store.dispatch(setCurrentUser(decoded));
// Check for expired token
const currentTime = Date.now() / 1000; // to get in milliseconds
if (decoded.exp < currentTime) {
// Logout user
store.dispatch(logoutUser());
// Redirect to login
window.location.href = "./login";
}
}
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Navbar />
<Route exact path="/" component={Landing} />
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Switch>
<PrivateRoute exact path="/dashboard" component={Dashboard} />
</Switch>
</div>
</Router>
</Provider>
);
}
}
export default App;

React Authentication using HOC

The server sends a 401 response if the user is not authenticated and I was trying to check for authentication in the front end using a HOC as seen in Performing Authentication on Routes with react-router-v4.
However, I am getting an error saying TypeError: Cannot read property 'Component' of undefined in RequireAuth
RequireAuth.js
import {React} from 'react'
import {Redirect} from 'react-router-dom'
const RequireAuth = (Component) => {
return class Apps extends React.Component {
state = {
isAuthenticated: false,
isLoading: true
}
async componentDidMount() {
const url = '/getinfo'
const json = await fetch(url, {method: 'GET'})
if (json.status !== 401)
this.setState({isAuthenticated: true, isLoading: false})
else
console.log('not auth!')
}
render() {
const { isAuthenticated, isLoading } = this.state;
if(isLoading) {
return <div>Loading...</div>
}
if(!isAuthenticated) {
return <Redirect to="/" />
}
return <Component {...this.props} />
}
}
}
export { RequireAuth }
App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, withRouter } from 'react-router-dom';
import SignIn from './SignIn'
import NavigationBar from './NavigationBar'
import LandingPage from './LandingPage'
import Profile from './Profile'
import Register from './Register'
import { RequireAuth } from './RequireAuth'
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Router>
<NavigationBar />
<Switch>
<Route exact path = '/'
component = {LandingPage}
/>
<Route exact path = '/register'
component = {Register}
/>
<Route exact path = '/profile'
component = {RequireAuth(Profile)}
/>
<Route path="*" component = {() => "404 NOT FOUND"}/>
</Switch>
</Router>
</div>
);
}
}
export default withRouter(App);
I can think of some possibilities:
------- Moved this to top which eventually fixed OP's issue -------
Try remove the curly braces at {React},
import React from 'react';
------- Moved this to top which eventually fixed OP's issue -------
In RequireAuth.js, Try
const RequireAuth = ({ Component }) => {} // changed from Component to { Component }
In App.js, use Component start with capital letter
<Route exact path = '/' Component = {LandingPage}/>
Also, in <Route path="*" component = {() => "404 NOT FOUND"}/>, looks like you're not passing in a React component because the function is not returning a JSX (I can't test now so I'm not very sure, though).
try this instead:
() => <div>404 NOT FOUND</div>
or if it doesn't work, define a functional component externally and pass into the Route:
const NotFoundComponent = () => <div>404 NOT FOUND</div>
<Route path="*" component = {NotFoundComponent}/>
try to do it like this:
const RequireAuth = ({ component: Component }) => {}

React Redux routing issues

I have recently experienced some issues with my react router and redux. Basically, I have a redux value set which let's me know if an item is selected. If the item is selected, then it will allow a URL to be used. One thing that I have noticed. If I add a redirect function. It breaks everything
Authentication function:
import React, { Component, Fragment } from "react";
import { Provider } from "react-redux";
// import store from "./store";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect
} from "react-router-dom";
import { connect } from "react-redux";
import Profile from "./Profile";
import AddDomain from "./AddDomain";
import ChoosePackage from "./ChoosePackage";
import DashboardHome from "./DashboardHome";
import { Elements } from "#stripe/react-stripe-js";
import PropTypes from "prop-types";
import { loadStripe } from "#stripe/stripe-js";
const stripePromise = loadStripe("pk_test_7S0QSNizCdsJdm9yYEoRKSul00z4Pl6qK6");
class index extends Component {
componentDidMount() {
console.log("DOMAIN NAME" + this.props.domain_name);
}
state = {
domain_name: ""
};
static propTypes = {
domain_name: PropTypes.string.isRequired
};
domainCheck = () => {
if (this.props.domain_name != "") {
return <ChoosePackage />;
} else {
console.log("running rediect");
return <Redirect to="/dashboard" />;
}
};
render() {
return (
<React.Fragment>
<Route path="/dashboard/add-domain/choose-package">
{this.domainCheck()}
</Route>
<Route exact path="/dashboard/add-domain">
<AddDomain />
</Route>
<Route exact path="/dashboard/profile">
<Profile />
</Route>
<Route exact path="/dashboard">
<DashboardHome />
</Route>
</React.Fragment>
);
}
}
const mapStateToProps = state => ({
domain_name: state.domain.domain_name
});
index.defaultProps = {
domain_name: ""
};
export default connect(mapStateToProps, { pure: false })(index);
Any help is greatly appreciated

React router grab URL segment in component

I'm using a simple router in React
<Router>
<div>
<Switch>
<Route path="/" component={ Home } exact />
<Route path="/contact" component={ Contact } />
<Route path="/:slug" component={ Post } />
</Switch>
</div>
</Router>
I'm pulling posts from a blog using REST and have a router component named Post for single blog posts. Any Route that doesn't match with home or contact, uses the post component.
How can I get or pass the route slug/url segment in the Post component? For example if the url segment/slug is /some-blog-post-title, I want to retrieve it, preferably using a React Router function/method if it exists.
You can get the parameters in the props.match.params object. To get your :slug parameter you would write props.match.params.slug.
Example
class Post extends React.Component {
componentDidMount() {
this.getPost(this.props.match.params.slug);
}
componentDidUpdate(prevProps) {
if (prevProps.match.params.slug !== this.props.match.params.slug) {
this.getPost(this.props.match.params.slug);
}
}
getPost = slug => {
// ...
};
render() {
return <h2>{this.props.match.params.slug}</h2>;
}
}
If you want to grab urls in a functional component
App.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import User from './User';
class App extends Component {
render() {
return (
<Router>
<Switch>
<Route exact path='/user/:userName' component={User} />
<Route>
<div>Default page</div>
</Route>
</Switch>
</Router>
);
}
}
export default App;
Inside the functional component you can grab it
import React from 'react';
import { useParams } from 'react-router-dom';
const User = () => {
const { userName } = useParams();
return (
<div>Username: { userName }</div>
);
}
export default User;

Categories