Integrating react-cookie with react redux - javascript

My main application is based on this old boilerplate which I have been slowly updating. Currently, all of the dependencies have been updated except for react-cookie.
I am trying to upgrade react-cookie to version 3.0.4 using this tutorial but I need some help overcoming some challenges I am facing during the transition process.
Following the tutorial, I changed index.js to
ReactDOM.render(
<CookiesProvider>
<Provider store={store}>
<App />
</Provider>
</CookiesProvider>,
document.querySelector('.wrapper'));
Now, my app.js file looks like this:
import React, { Component } from 'react'
import { withCookies } from 'react-cookie'
import Routes from '../Routes'
class App extends Component {
render() {
return (
<div className="container">
<Routes cookies={this.props.cookies} />
</div>
);
}
}
export default withCookies(App)
Now, my biggest concern comes here. My Routes component was never meant to be a Redux container so I changed it to this to accommodate the tutorial:
import React from 'react'
import { connect } from 'react-redux'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import ScrollUpButton from 'react-scroll-up-button'
// Import miscellaneous routes and other requirements
import NotFoundPage from './components/pages/not-found-page'
// Import Header and footer
import HeaderTemplate from './components/template/header'
import FooterTemplate from './components/template/footer'
// Import static pages
import HomePage from './components/pages/home-page'
// Import authentication related pages
import Register from './components/auth/register'
import Login from './components/auth/login'
import Logout from './components/auth/logout'
import ForgotPassword from './components/auth/forgot_password'
import ResetPassword from './components/auth/reset_password'
import ConfirmationMessage from './components/auth/confirmation_message'
import ResendVerificationEmail from './components/auth/resend_verification_email'
// Import dashboard pages
import Dashboard from './components/dashboard/dashboard'
import ChangePassword from './components/dashboard/profile/change-password'
// Import simulator pages
import Simulator from './components/simulator/index'
// Import higher order components
import RequireAuth from './components/auth/require_auth'
const BrowserRoutes = () => (
<BrowserRouter>
<div>
<HeaderTemplate logo="Stress Path Simulator" />
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/logout" component={Logout} />
<Route exact path="/forgot-password" component={ForgotPassword} />
<Route exact path="/reset-password/:resetToken" component={ResetPassword} />
<Route exact path="/confirmation-message" render={() => <ConfirmationMessage message="Please click on the link we sent to your email to verify your account." /> } />
<Route exact path="/resend-verification-email" component={ResendVerificationEmail} />
<Route exact path="/profile/change-password" component={RequireAuth(ChangePassword)} />
<Route exact path="/confirmation-password-changed" render={() => RequireAuth(<ConfirmationMessage message="Password has been successfully changed!" />)} />
<Route exact path="/simulator" component={RequireAuth(Simulator)} />
<Route exact path="/dashboard" component={RequireAuth(Dashboard)} />
<Route component={NotFoundPage} />
</Switch>
<FooterTemplate />
<ScrollUpButton />
</div>
</BrowserRouter>
);
const mapStateToProps = (state, ownProps) => {
return ({
state: state,
cookies: ownProps.cookies
});
}
export const Routes = connect(mapStateToProps, null)(BrowserRoutes)
export default Routes
I believe the problem essentially arises here. By doing so, I thought I would have been able to use the cookies from every single component like this:
//get this.props.cookies
const { cookies } = this.props;
//setting a cookie
cookies.set('name', 'Ross', { path: '/' });
//getting a cookie
cookies.get('name');
However, that doesn't seem the case and I cannot get cookies to work in any of my components especially in my actions/auth.js.
Does anyone have any suggestions? How can I efficiently use cookies in this scenario? I am assuming I can send down the cookies prop to each component that needs it but I am curious to find out what could be the best/cleanest way of using react-cookie with redux. I am fairly new to the MERN JavaScript software stack and mostly self-thought so I am a bit confused about some concepts. For example, if in Routes I am saving cookies into the redux's store, how can I access those cookies afterwards?

Instead of passing the cookies from the App/Router down, it is better to wrap only the components that will need the cookies. For example your Login component would look like this:
class Login extends React.Component {
render() {
let { cookies } = this.props;
let useCookie = cookies.get("testCookie");
...
}
}
export default withCookies(connect(mapStateToProps, null)(Login));

Related

React router dom navigate method is not working properly

Hei, I am trying to build a simple react app with a navigation feature. The main theme is I have 3 components, App, Test, and AppShell. App component is the default(Initial) component. And what I want is that Every time user goes to App component, my app will redirect to Test component.
The problem I am facing is that my redirection only works when I load the application the first time, after that my redirection is not working.
I am sharing my three components code below along with the index page!
Index page
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router,
Routes,
Route
} from "react-router-dom";
ReactDOM.render(
<Router>
<Routes>
<Route path='/' element={<App />} />
<Route path='/test' element={<Test />} />
</Routes>
</Router>,
document.getElementById('root')
);
function Test() {
return <h1>Test Me</h1>;
}
reportWebVitals();
App Component
import "./App.css";
import AppShell from "./components/core/appShell";
import { useNavigate } from 'react-router-dom';
export default function App(props) {
let navigate = useNavigate();
return <AppShell {...props} navigate={navigate} />;
}
App shell component
import React, { Component } from 'react';
import { Outlet } from "react-router-dom";
class AppShell extends Component {
componentDidMount() {
this.props.navigate('/test');
}
render() {
return (
<div>
<h1>This is app shell</h1>
<Outlet />
</div>
);
}
}
export default AppShell;
I thought the problem is lies within component hooks, so I tried to implement the redirection inside the constructor too, but nothing is working for me!
The basic business problem I am trying to solve here is - A user will be redirected to a login page, every time he/she tries to browse another page regardless of valid login(valid user) could be based on the valid token on local storage
Could anyone say, What I am doing wrong?
Authentication with regards to protected routes is actually pretty trivial in react-router-dom v6
Create a wrapper component that accesses the auth context (local state, redux store, local storage, etc...) and based on the auth status renders an Outlet component for nested routes you want to protect, or a redirect to your auth endpoint.
Example AuthWrapper:
const AuthWrapper = () => {
const location = useLocation();
const token = !!JSON.parse(localStorage.getItem("token"));
return token ? (
<Outlet />
) : (
<Navigate to="/login" replace state={{ from: location }} />
);
};
Uses:
useLocation hook to grab the current location user is attempting to access.
Outlet component for nested protected routes.
Navigate component for declarative navigation, sends the current location in route state so user can be redirected back after authenticating.
Example Usage:
<Router>
<Routes>
<Route element={<AuthWrapper />}>
<Route path="/" element={<App />} />
</Route>
<Route path="/login" element={<Login />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</Router>
Login - In the authentication handler, once authenticated, set the localStorage and navigate to the location that was passed in route state.
function Login() {
const { state } = useLocation();
const navigate = useNavigate();
const { from = "/" } = state || {};
const login = () => {
localStorage.setItem("token", JSON.stringify(true));
navigate(from);
};
return (
<>
<h1>Test Me</h1>
<button type="button" onClick={login}>Log In</button>
</>
);
}

Web page is blank (Problem with react-router)

I am trying to learn MERN mainly react by following a tutorial (https://www.youtube.com/watch?v=7CqJlxBYj-M) and I have followed the code exactly but when I run the server and open the web page it is blank.
I know the problem is with the four React route paths because if I remove them the web page displays the navbar. I also get no errors when running the server.
this is the app.js file code:
import React from 'react';
import "bootstrap/dist/css/bootstrap.min.css";
import { BrowserRouter as Router, Route,} from "react-router-dom";
import Navbar from "./components/navbar.component"
import ExercisesList from "./components/exercises-list.component";
import EditExercise from "./components/edit-exercise.component";
import CreateExercise from "./components/create-exercise.component";
import CreateUser from "./components/create-user.component";
function App() {
return (
<Router>
<div className="container">
<Navbar />
<br/>
<Route path="/" exact component={ExercisesList} />
<Route path="/edit/:id" component={EditExercise} />
<Route path="/create" component={CreateExercise} />
<Route path="/user" component={CreateUser} />
</div>
</Router>
);
}
export default App;
This is the code for create-exercise:
import React, { Component } from 'react';
export default class CreateExercise extends Component{
render() {
return (
<div>
<p>You are on the create exercises List componentt</p>
</div>
)
}
}
The other three have the same code.
This is the link to the github containing the tutorial's code:
https://www.youtube.com/redirect?event=video_description&redir_token=QUFFLUhqa3VfM2thaXc4b1RoODUxWkh0MXprN2NFV3E2QXxBQ3Jtc0trbTdTQll1WmVFQ1hRb0ZOVWlUVVROUG1ta2RranJocVFmektvb0F0VWpKQjNWY0tIelBuZ1ZLNDU5VVFhSVZiS3VGTnJHT19ja0NYdVI3OFdkZVVQS0ZoLV8wQkxhT2xqeS0yakNPSXNyZjlLTW5Vbw&q=https%3A%2F%2Fgithub.com%2Fbeaucarnes%2Fmern-exercise-tracker-mongodb
In React-Router version 6 you need to use element
https://reactrouter.com/docs/en/v6/getting-started/tutorial#add-some-routes
Example:
<Route path="/" element={<App />} />
<Route path="expenses" element={<Expenses />} />
<Route path="invoices" element={<Invoices />} />

problems on page refresh

I have built an admin panel using react. After logging in to the panel whenever the user refreshes the page, everything disappears, I don't know why its happening.
Its working fine without the signin page but after adding the signin page it doesn't.
Here is the App.js file code where all the Routes are defined.
import React, { useState } from "react";
import { Route, Switch } from "react-router-dom";
import { Link } from "react-router-dom";
import * as FaIcons from "react-icons/fa";
import SideMenu from "./SideMenu";
import Dashboard from "./components/Dashboard";
import Registration_Request from "./components/Registration_Request";
import Users from "./components/Users";
import Seller from "./components/Request Pages/Seller";
import Reseller from "./components/Request Pages/Reseller";
import Sales from "./components/Request Pages/Sales";
import Sellers from "./components/Sellers";
import Character_Upload from "./components/Character_Upload";
import Campaign_Design from "./components/Campaign_Design";
import Levels_Design from "./components/Levels_Design";
import SellingCoins from "./components/SellingCoins";
import SignIn from "./SignIn";
function App() {
let [signedIn, isSignedIn] = useState(false);
return (
<>
<div className="header"></div>
<div className="main-content">
<Switch>
<Route path="/" exact>
<SignIn signedIn={signedIn} isSignedIn={isSignedIn} />
</Route>
{signedIn && (
<>
<SideMenu />
<Route path="/dashboard" exact component={Dashboard} />
<Route path="/registration-request/seller" component={Seller} />
<Route
path="/registration-request/reseller"
component={Reseller}
/>
<Route path="/registration-request/sales" component={Sales} />
<Route path="/users" component={Users} />
<Route path="/sellers" component={Sellers} />
<Route path="/character-upload" component={Character_Upload} />
<Route path="/campaign-design" component={Campaign_Design} />
<Route path="/levels-design" component={Levels_Design} />
<Route path="/sellingcoins" component={SellingCoins} />
</>
)}
</Switch>
</div>
</>
);
}
export default App;
The signedIn state only lives in memory, and the initial value is false. When you reload the page, you reload the app, which remounts/reinitializes the components.
The solution is typically to persist your app state to local storage, and initialize from localStorage.
Using a state lazy initializer function you can read the localStorage for the saved state and set the initial state.
const [signedIn, isSignedIn] = useState(() => {
return !!JSON.parse(localStorage.getItem("signedIn"));
});
Use an useEffect hook to persist state changes to localStorage. When a user signs in and the signedIn state updates, this will trigger the useEffect hook's callback and will save the state value into localStorage.
useEffect(() => {
localStorage.setItem("signedIn", JSON.stringify(signedIn));
}, [signedIn]);
The signedIn flag will be set to false on page refresh. Instead of using it in the state variable use the local Storage/ Session Storage.
you can read more about local storge

React Router v5 nested routes not found

I'm having problems trying to make a simple setup to run. I have used "react-router-dom" because it claims to be the most documented router around.
Unfortunately, the documentation samples are using functions instead of classes and I think a running sample will not explain how routes have changed from previous versions... you need a good sight!. Btw, there are a lot of breaking changes between versions.
I want the following component structure:
Home
Login
Register
Recipes
Ingredients
Have the following components:
index.js (works fine)
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route } from 'react-router-dom';
import App from './App';
ReactDOM.render((
<BrowserRouter>
<Route component={App}/>
</BrowserRouter>
), document.getElementById('root'));
App.js (fine)
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import Home from './Home'
import Recipes from './recipes/Recipes'
import Ingredients from './ingredients/Ingredients'
class App extends React.Component {
render() {
return (
<div id="App">
<Switch>
<Route exact path='/home' component={Home} />
<Route path='/recipes' component={Recipes} />
<Route path='/ingredients' component={Ingredients} />
<Route render={() => <h1>Not found!</h1>} />
</Switch>
</div>
);
}
}
export default YanuqApp;
Ingredients and Recipes components working fine, so I'll skip from here
Home.js - The problem starts here. Home itself loads correctly, but once Login or Register links are clicked, it shows "Not found!" (fallback route in App.js)
import React from 'react';
import { Switch, Route, Link } from 'react-router-dom';
import Register from './account/register'
import Login from './account/login'
class Home extends React.Component {
render() {
return (
<div>
<div>
This is the home page...<br/>
<Link to='/home/login'>Login</Link><br />
<Link to='/home/register'>Register</Link><br />
</div>
<Switch>
<Route path='/home/login' component={Login} />
<Route path='/home/register' component={Register} />
</Switch>
</div>
);
}
}
export default Home;
Login and register are very similar:
import React from 'react';
class Login extends React.Component {
render() {
alert("login");
return (
<div>Login goes here...</div>
);
}
}
export default Login;
And cannot figure why Login and Register are not found. I have tried also defining routes as:
<Link to={`${match.path}/register`}>Register</Link>
...
<Route path={`${match.path}/register`} component={Register} />
(don't see the gain on using match, as it renders as the expected "/home/register"), but the problem persists in identical way
I think it's because of the exact flag on the Route for home. It does not match the /home exact so it goes to the default not found page.
try to add this in App.js
<Switch>
<Route exact path='/' component={Home} />
<Route path='/recipes' component={Recipes} />
<Route path='/ingredients' component={Ingredients} />
<Route path='/login' component={Login} />
<Route path='/register' component={Register} />
<Route render={() => <h1>Not found!</h1>} />
</Switch>
to this is work
<Link to={`${match.path}/register`}>Register</Link>
...
<Route path={`${match.path}/register`} component={Register} />
you should provide match as the props because cont access directly to the match to used it you should provide a match as this following
const namepage=({match})=>{
<Link to={`${match.path}/register`}>Register</Link>
...
<Route path={`${match.path}/register`} component={Register} />
})

Matched route not changing on routing hash change

I'm using react-router-dom with react-router-redux and history to manage routing for my app. I'm also using hash history for support on legacy browsers. Below are my route components:
<Switch>
<Route exact path={'/'} component={...} />
<Route path={'/a'} component={...} />
<Route path={'/b'} component={...} />
</Switch>
My app lands at the location: http://something.com/index.html#/, and correctly is routed to the first Route component. However, when using dispatch(push('/a')) in a thunk action creator to attempt to programatically switch routes, I'm finding that the proper route is not being matched.
I'm having a difficult time debugging this... any ideas? I'm thinking it perhaps has to do with the fact that my window.location.pathname is /index.html.
Switch receive a location prop, or must be wrapped with Router component. You can find more information at https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Switch.md#children-node/
If a location prop is given to the , it will override the location prop on the matching child element.
So try one of these ways:
class Example extends Component {
render() {
return (
<Switch location={this.props.location}>
<Route exact path={'/'} component={...} />
<Route path={'/a'} component={...} />
<Route path={'/b'} component={...} />
</Switch>
);
}
// location is react-router-redux reducer
export default connect(state => ({location: state.location}))(Example);
Or, another way you can do, it's wrap your Switch component with Router component (I pasted code from one of my project):
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { Route, Switch } from 'react-router-dom';
import { ConnectedRouter } from 'react-router-redux';
import createHistory from 'history/createBrowserHistory';
import configureStore from './store/configureStore';
const history = createHistory();
const store = configureStore(history);
// We wrap Switch component with ConnectedRouter:
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<Switch>
<Route exact path={'/'} component={...} />
<Route path={'/a'} component={...} />
<Route path={'/b'} component={...} />
</Switch>
</ConnectedRouter>
</Provider>,
document.getElementById('root')
);
More information about Router components you can find here: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Router.md

Categories

Resources