How to use layout components in react.js with react-router - node.js

I am working on my first react application with redux and react-router( also using react-router-redux). I want a way to present two different layouts; one layout when the user has not signed in and another when the user has signed in.
Please I would like to know how to fix this in my code or how to achieve the expected result otherwise.
Below is what I have tried:
Created the root component App.js that reads the value from the state of the store to know if the user is logged in.
import React, { Component } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
//Import Components
import Main from '../components/Main'
//Import necessary actions
import * as loginActions_ from '../actions/login'
const mapStateToProps = (state) => {
return {
loginStatus: state.loginStatus
}
}
const mapDispatchToProps = (dispatch) => {
const loginActions = bindActionCreators (loginActions_, dispatch)
return {
loginActions
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Main)
Created a presentation(Main.js) component that uses the loginStatus to render the appropriate layout.
import React, { Component } from 'react'
import { Container } from 'semantic-ui-react'
import MainLayoutOut from './MainLayoutOut'
import MainLayoutIn from './MainLayoutIn'
export default class Main extends Component {
constructor(props){
super(props)
}
render(){
const child = (this.props.loginStatus? <MainLayoutIn loginStatus={this.props.loginStatus} loginActions={this.props.loginActions} />
: <MainLayoutOut loginStatus={this.props.loginStatus} loginActions= {this.props.loginActions} /> )
return(
<Container>
{child}
</Container>
)
}
}
The MainLayoutOut.js which renders it's own Menu, Content(the children) and a footer.
import React, {Component} from 'react'
import {Container, Segment } from 'semantic-ui-react'
import Footer from './Footer'
import MenuOut from './MenuOut'
export default class MainLayoutOut extends Component {
constructor(props){
super(props)
}
render(){
return(
<Container fluid>
<MenuOut/>
<Segment key='contentOut'>
{React.cloneElement(this.props.children, this.props)}
</Segment>
<Footer/>
</Container>
)
}
}
Similarly, the MainLayoutIn.js has the structure below:
import React, {Component} from 'react'
import {Container, Segment, Header} from 'semantic-ui-react'
export default class MainLayoutIn extends Component {
constructor(props){
super(props)
}
render(){
return(
<Container>
<Segment key='menuIn'>Header In</Segment>
<Segment key='contentIn'>
<Header as='h1'>Content In</Header>
{/*this.props.children*/}
</Segment>
<Segment key='footerIn'>FooterIn</Segment>
</Container>
)
}
}
Below is how I created the store.
import { applyMiddleware, createStore } from 'redux'
import createLogger from 'redux-logger'
import ReduxThunk from 'redux-thunk'
import initialState from '../initialState'
import rootReducer from '../reducers'
const logger = createLogger()
const middlewares = [ReduxThunk, logger]
export default function configureStore(initialStateParam = initialState){
return createStore(rootReducer, {}, applyMiddleware(...middlewares));
}
The reducers the root-reducers; reducers/index.js
import { combineReducers } from 'redux'
import { routerReducer } from 'react-router-redux'
import loginStatus from './loginStatus'
const rootReducer = combineReducers({
routing: routerReducer,
loginStatus
})
export default rootReducer
and the loginStatus reducer for now is like:
export default function loginStatus(state = false, action){
console.log('Login Status fired!')
return state
}
Lastly the client.js file that sets up the application.
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { syncHistoryWithStore } from 'react-router-redux'
import { Router, Route, IndexRoute, browserHistory } from 'react-router'
import configureStore from '../src/store/configureStore'
import App from '../src/containers/App'
import Main from '../src/components/Main'
import MainLayoutIn from '../src/components/MainLayoutIn'
import MainLayoutOut from '../src/components/MainLayoutOut'
import Blog from '../src/components/Blog'
import SignUp from '../src/components/SignUp'
import Login from '../src/components/Login'
const store = configureStore()
const history = syncHistoryWithStore(browserHistory, store)
const router = (
<Provider store={store}>
<Router history={history}>
<Route path='/' component={App}>
<Route path='/' component={Main}>
<Route path='/' component={MainLayoutOut}>
<IndexRoute component={Blog}></IndexRoute>
<Route path='/login' component={Login}/>
<Route path='/signup' component={SignUp}/>
</Route>
<Route path='/' component={MainLayoutIn}>
</Route>
</Route>
</Route>
</Router>
</Provider>
)
render( router ,document.getElementById('app'))
The client.js file is to route the components of the app. I want that when a user login he should land on a page(the purpose MainLayoutOut.js) having a menu (with menu-items to access a list of blogs, sign up, and login) a content and footer. But when the user authenticates and is authorized he is suppose to see completely different layout (the purpose of MainLayoutIn.js) with its own Menu, content, and footer.
Running the above code yields the error message:
Uncaught TypeError: Cannot read property 'props' of undefined
at Object.ReactElement.cloneElement (http://localhost:3000/bundle.js:6362:35)
at Object.cloneElement (http://localhost:3000/bundle.js:23625:49)
at MainLayoutOut.render (http://localhost:3000/bundle.js:17164:28)
at MainLayoutOut.tryRender (http://localhost:3000/bundle.js:3912:32)
at MainLayoutOut.proxiedMethod (http://localhost:3000/bundle.js:52020:31)
at http://localhost:3000/bundle.js:44855:22
at measureLifeCyclePerf (http://localhost:3000/bundle.js:44134:13)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (http://localhost:3000/bundle.js:44854:26)
at ReactCompositeComponentWrapper._renderValidatedComponent (http://localhost:3000/bundle.js:44881:33)
at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3000/bundle.js:44421:31)

Related

redux gets two errors in React.js

I want to create a cart for a shopping mall,
when I use the redux ,which always comes two errors(Problem A&B).
Problem A.
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
Problem B.
Uncaught TypeError: Cannot read properties of null (reading 'useMemo')
at useMemo (react.development.js:1650:1)
at Provider (Provider.js:12:1)
at renderWithHooks (react-dom.development.js:16305:1)
at mountIndeterminateComponent (react-dom.development.js:20074:1)
at beginWork (react-dom.development.js:21587:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at beginWork$1 (react-dom.development.js:27451:1)
at performUnitOfWork (react-dom.development.js:26557:1)
As the photo below:
Data structures:
cartRedux>>store>>index.js
useSelector>>Nav.jsx(which shows the console.log() )
here are my relative data:
cartRedux.js
import {createSlice} from "#reduxjs/toolkit"
const cartSlice=createSlice({
name:"cart",
initialState:{
products:[],
quantity:0,
total:0,
},
reducers:{
addProduct:(state,action)=>{
state.quantity+=1;
state.products.push(action.payload.product);
state.total+=action.payload.price;
},
}
})
export const {addProduct}=cartSlice.actions;
export default cartSlice.reducer;
store.js
import {configureStore} from "#reduxjs/toolkit";
import cartReducer from "./cartRedux";
export default configureStore({
reducer:{
cart:cartReducer,
}
})
index.js and the error always metioned the Provider,but it is imported from react-redux.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { Provider } from "react-redux";
import store from './redux/store';
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
Nav.jsx
import React from 'react'
import {useSelector} from 'react-redux';
import Styled from 'styled-components';
const Container = Styled.div`
width:100%;
color: black;
height:max-content;
`;
const Nav = () => {
const cart=useSelector(state=>state.cart)
console.log(cart);
return (
<Container/> .....
)
}
export default Nav

react-router-dom: how to create route with regex capture groups in url and get them in the component

I want to create a page in reactjs for the following regex url
^rest-auth/password-reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$
And i want to capture uidb64 and token in my component
Can any one guide how to write route with regex
I am using the
"react-router": "^5.2.0",
"react-router-dom": "5.2.0",
"react-dom": "16.13.1",
"react": "16.13.1",
currently i have
import React from "react";
import ReactDOM from "react-dom";
import { createBrowserHistory } from "history";
import { Router, Route, Switch, Redirect } from "react-router-dom";
import Login from "./views/User/Login";
import Signup from "./views/User/SignUp";
import ForgotPasswordSendEmail from "./views/User/ForgotPasswordSendEmail";
const hist = createBrowserHistory();
ReactDOM.render(
<Router history={hist}>
<Switch>
<Route path="/signup" component={Signup} />
<Route path="/login" component={Login} />
<Route path="/forgort-password-send-email" component={ForgotPasswordSendEmail} />
<Redirect from="/" to="/login" />
</Switch>
</Router>,
document.getElementById("root")
);
Now i want to add a Component called ResetPassword something like below
import ResetPassword from "./views/User/ResetPassword";
<Route path="/rest-auth/password-reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$" component={ResetPassword} />
and my ResetPassword Component looks like
import React, { useState, useEffect } from "react";
export default function ResetPassword() {
// Here how to capture the urls capture groups
// and then store then as follows
const uid = uid64;
const token = token;
return (
<div>
{uid} -- {token}
</div>
}
HOw to do routing with regex capture groups and how to get them in my component.
To Capture regex groups we have to use /name:regex and use useParams hook
<Route path="/rest-auth/password-reset/confirm/uidb64:([0-9A-Za-z_\-]+)/token:([0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$" component={ResetPassword} />
and inside ResetPassword
import React, { useState, useEffect } from "react";
import {useParams} from 'react-router-dom'
export default function ResetPassword() {
let params = userParams()
const uid = params.uid64;
const token = params.token;
return (
<div>
{uid} -- {token}
</div>
}

reactjs - sidebar not working after store update

I am using reactjs.
node: version 14
I am developing on core-ui-react-template.
Sidebar did not work after updating the ./store file. I put the contents of the store file and index.js file below.
original website core.io
I have been working on it for a few days but I could not get any results. I couldn't find where was the mistake
index.js
import 'react-app-polyfill/ie11'; // For IE 11 support
import 'react-app-polyfill/stable';
import './polyfill'
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { icons } from './assets/icons'
import store from './store'
import { transitions, positions, Provider as AlertProvider } from 'react-alert'
import AlertTemplate from 'react-alert-template-basic'
import {Provider} from 'react-redux';
import ReactNotification from 'react-notifications-component';
import 'react-notifications-component/dist/theme.css'
React.icons = icons;
const options = {
position: positions.BOTTOM_RIGHT,
timeout: 5000,
offset: '1px',
transition: transitions.SCALE,
};
console.log(store.getState());
ReactDOM.render(
<Provider store={store}>
<AlertProvider template={AlertTemplate} {...options}>
<ReactNotification/>
<App/>
</AlertProvider>
</Provider>,
document.getElementById('root')
);
serviceWorker.unregister();
./store.js
import {applyMiddleware, combineReducers, compose, createStore} from "redux";
import customerReducer from "./components/helpers/reducers/customerReducer";
import userReducer from "./components/helpers/reducers/userReducer";
import appointmentsReducer from "./components/helpers/reducers/appointmenstReducer";
import thunk from "redux-thunk";
const initialState = {
sidebarShow: 'responsive'
};
const changeStateReducer = (state = initialState, { type, ...rest }) => {
switch (type) {
case 'set':
return {...state, ...rest };
default:
return state
}
};
const rootReducers = combineReducers({
customerInfo: customerReducer,
account_profile: userReducer,
appointmentsList: appointmentsReducer,
changeState: changeStateReducer
});
const allEnhancers = compose(
applyMiddleware(thunk)
);
const store = createStore(
rootReducers,
allEnhancers
);
export default store
As you know, I use core-ui-react template. There is a link below.
But after updating the ./store file, it shows "undefined" when I show it with console.log (sidebarShow) in "const sidebarShow = useSelector (state => state.sidebarShow)" line in TheHeader file.
https://github.com/coreui/coreui-free-react-admin-template/blob/master/src/containers/TheHeader.js
I think "useSelector (state => state.sidebarShow)" doesn't get the function here. It originates from here.
check out how combineReducers works: https://redux.js.org/api/combinereducers
your selector should be:
const sidebarShow = useSelector(state => state.changeState.sidebarShow)
you'll notice that changeState is not a very good key name, but that is another issue :)

Failed to compile ./src/App.js Attempted import error: 'UserProvider' is not exported from './model/UserContext'

I'm getting the following error, a would love it if someone could point me in the right direction :)
Failed to compile ./src/App.js Attempted import error: 'UserProvider'
is not exported from './model/UserContext'.
UserContext.js
const UserProvider = ({ children, history}) => { ... })
export default withRouter(UserProvider);
app.js
import React from 'react';
import NavBar from './components/navBar';
import Login from './components/login';
import Session from './components/session';
import Dashboard from './components/dashboard';
import './App.css';
import Container from '#material-ui/core/Container';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import { UserProvider } from './model/UserContext'
function App() {
return (
<div>
<UserProvider>
<Session />
<NavBar />
<Container maxWidth="sm">
<Router>
<Route path='/Login' component={Login} />
<Route path='/Dashboard' component={Dashboard} />
</Router>
</Container>
</UserProvider>
</div>
);
}
export default App;
You are exporting UserProvider as default. So in App.js just import like below(Without curly braces).
import UserProvider from './model/UserContext'
import { UserProvider } from './model/UserContext'
You need to write like:
import UserProvider from './model/UserContext'

Common use redux's store between Nodejs and React

There are example how to create store in React:
//store/index.js
import { createStore, applyMiddleware } from 'redux'
import reducer from '../reducer'
const store = createStore(reducer)
export default store
//components/root.js
import App from './App'
import store from '../store'
import {Provider} from 'react-redux'
function Root() {
return (
<Provider store = {store}>
<App />
</Provider>
)
}
export default Root
So, I import 'redux' and 'react-redux'.
I wanna to create store in nodejs, then after user will be authentificated, add to store user's nick and some data, and send for user 'index.html', which written by React and will be use this store, created before. Is it possible, and how I can create store in Nodejs ? (in React I use methods {createStore}, {Provider} from 'react-redux' for this)

Resources