Routing Issues in React-Redux - react-redux

I'm new to the React-Redux ecosystem, learning by trying out simple applications.
In this case I'm trying out how routing works in the react-redux application.
Basically, the idea is :
Navigate to a new page by clicking a Link( a react-router
component)
Navigate to a new page upon successful completion of dispatched async action.
Here's my code
import React from 'react'
import {Link} from 'react-router'
import {routerActions} from 'react-router-redux'
import {connect} from 'react-redux'
class App extends React.Component {
render() {
// And you have access to the selected fields of the State too!
return (
<div>
<header>
Links:
{' '}
<Link to="/">Home</Link>
{' '}
<Link to="/foo">Foo</Link>
{' '}
<Link to="/bar">Bar</Link>
</header>
<div>
<button onClick={() => routerActions.push('/foo')}>Go to /foo</button>
</div>
</div>
)
}
}
export default connect(null, null)(App);
===================================================================
import React from 'react'
import {connect} from 'react-redux'
class Foo extends React.Component {
render() {
return (
<div> <h1>I'm Foo</h1> </div>
)
}
}
export default connect(null, null)(Foo);
===================================================================
import React from 'react'
import {connect} from 'react-redux'
class Bar extends React.Component {
render() {
return (
<div> <h1>I'm bar</h1> </div>
)
}
}
export default connect(null, null)(Bar);
===================================================================
import React from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import {Router, Route, browserHistory} from 'react-router'
import {syncHistoryWithStore} from 'react-router-redux'
import configureStore from './store'
import App from './components/test/App';
import Bar from './components/test/Bar';
import Foo from './components/test/Foo';
// Get the store with integrated routing middleware.
const store = configureStore()
// Sync browser history with the store.
const history = syncHistoryWithStore(browserHistory, store)
// And use the prepared history in your Router
ReactDOM.render(
<Provider store={store}>
<div>
<Router history={history}>
<Route path="/" component={App}>
<Route path="/foo" component={Foo}/>
<Route path="/bar" component={Bar}/>
</Route>
</Router>
</div>
</Provider>,
document.getElementById('root')
===================================================================
import {combineReducers,createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import userReducer from './reducers/reducer-user';
import {routerMiddleware,routerReducer} from 'react-router-redux'
import {browserHistory} from 'react-router'
export default function configureStore() {
// Create the routing middleware applying it history
const browserMiddleware = routerMiddleware(browserHistory);
const logger = createLogger();
const reducer = combineReducers({
userState: userReducer,
routing: routerReducer
})
const store = createStore(reducer,applyMiddleware(thunk,browserMiddleware,logger));
return store;
}
The application builds fine and it comes up well but when i click on the link, it does not work.
See screen shot of the running application
Searched around and read various posts but i could not pinpoint the root problem.

Your code seems to be correct, but there is a simple thing you are missing: you are not rendering the "child" of your router! :)
You can check that out here:
https://github.com/reactjs/react-router-tutorial/tree/master/lessons/04-nested-routes#sharing-our-navigation
Whenever you want to render a component route (the one you declared using </Route path="application-path" component={MyComponent} />), you need to specify where it will be placed. Using react-router, you specify this using the children prop. Then, whenever React "sees" this prop, it will render your routes (it can be a nested route too).
So, to fix your code, your App component needs to handle this.props.children correctly. Something like that:
class App extends React.Component {
/* ... */
render() {
return (
<div>
<header>Links go here</header>
{this.props.children}
</div>
)
}
}
Now, when you hit "/foo" route, this.props.children will be replaced by Foo component.
By the way, your nested routes (those inside ) don't need to have "/", since they will be "prepended". This is the way react-router render nested routes.
I think that is it, good luck with that! :)

Related

Conditional render with svelte kit for protect routes with token of sessionStorage

Im trying to generate a conditional render for protect routes with token. But i have the problem that when i enter the route with token first, for one second, is rendered the error page.
Code:
<script>
import Successlogin from '$lib/Login/Successlogin.svelte';
import { browserLocalGet, browserGet } from '$lib/Browser/index';
import ErrorPage from '$lib/ErrorPage/index.svelte';
import { writable } from 'svelte/store';
let routeSecurity = writable({
accessToken: browserGet('accessToken'),
emailForVerify: browserLocalGet('emailForSignIn')
});
</script>
{#if $routeSecurity.accessToken || $routeSecurity.emailForVerify}
<Successlogin />
{:else}
<ErrorPage
status={403}
title="Forbidden Access"
description="Please, check that you are login."
/>
{/if}

Vue.component alternative in Vue 3

I'm using Vue with Laravel Mix. In Vue version 2, I was able to do this:
1. resources/js/app.js:
import Vue from 'vue';
import MyComponent from './MyComponent';
Vue.component('my-component', MyComponent);
2. resources/js/MyComponent.vue:
<template>
<p>{{message}}</p>
</template>
<script>
export default {
name: "MyComponent",
props: ['message']
}
</script>
As this Vue 2 document instructed. I know it was not the best practice, but it was the only approach that I have to conveniently pass data from Laravel's Blade template to the component, such as below:
3. anyview.blade.php:
<my-component :message='message' id='app'></my-component>
<script src='public/js/app.js'><script> //include compiled resources/js/app.js
<script>
let app = new Vue({
el: '#app',
data() {
return {
message: 'Hello World';
}
}
})
</script>
In real case, 'Hello World' would be replaced with something like:
message: {{$myMessaGe}}
But since Vue 3, Vue.component is no longer a thing because Vue object is not a default export.
This work flow (1-2-3) has been seamlessly fine, so returning to Vue2 is the last unhappy choice :(
I have tried to work around, just changing Vue.component with the new createApp:
4. resources/js/app.js:
import { createApp } from 'vue';
import MyComponent from './MyComponent';
createApp({
components: {
MyComponent,
}
}).mount('#app');
But instead of adding MyComponent to current instance, it just creates a new one as depicted below - meaning that the prop message can't be passed through.
My question is: Is there any alternative API or workaround to compensate the loss of Vue.component()?
I have only worked with Vue3 so far but what I understand from the documentation is that the components in Vue3 are not that different from components in Vue2.
Try this solution:
import { createApp } from 'vue';
import MyComponent from './MyComponent';
const app = createApp({});
app
.component('MyComponent', MyComponent)
.mount('#app');
You can find more about this in the Vue3 docs.

How can I programatically show/hide editLink client side in Vuepress 2?

I want to show the edit link only for privileged users. I have user information that I am using for example for routing, and I can use it in components. However, I have not found any way to show/hide the edit link on each page based on the user roles. It must be done client side. Please help.
I found a way to do this:
Follow the instructions to extend the default theme.
Make your own EditLink component like this:
// EditLink.vue
<template></template>
<script setup>
import { onMounted } from "vue";
import { usePageFrontmatter } from "#vuepress/client";
onMounted(() => {
const fm = usePageFrontmatter();
fm.value.editLink = true; // Replace true with your logic
});
</script>
In the Layout component (see instructions linked above) do this:
// Layout.vue
<template>
<Layout>
<template #page-bottom> <EditLink /></template>
</Layout>
</template>
<script setup>
import Layout from "#vuepress/theme-default/lib/client/layouts/Layout.vue";
import EditLink from "../components/EditLink";
</script>

Why do I need to import "VToolbarItems"?

I see examples of using Vuetify in which only the template is show and there is no importing of Vuetify components like VTool, much less VToolTitle, VToolItems, etc. But if I don't import and declare them I get "Unknown custom element: ..."
I did not load vuetify with "vue add vuetify". Is that necessary? Is there something missing that I can add, if so?
In my main.js I have:
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
import App from './App.vue'
Vue.config.productionTip = false
Vue.use(Vuetify)
new Vue({
render: h => h(App),
}).$mount('#app')
This App.vue works:
<template>
<v-app id="vuetify-app">
<v-toolbar>
<v-toolbar-title>
Pro
</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items class="hidden-sm-and-down">
<v-btn flat>List</v-btn>
<v-btn flat>Profile</v-btn>
<v-btn flat>Help</v-btn>
</v-toolbar-items>
</v-toolbar>
<SignUp msg="Welcome"/>
</v-app>
</template>
<script>
import {VApp, VToolbar, VToolbarTitle, VToolbarItems, VSpacer, VBtn} from 'vuetify/lib'
import SignUp from './components/SignUp.vue'
export default {
name: 'App',
components: {
VApp,
VToolbar,
VToolbarTitle,
VToolbarItems,
VSpacer,
VBtn,
SignUp
}
}
</script>
But if I comment out:
import {VApp, VToolbar, VToolbarTitle, VToolbarItems, VSpacer, VBtn} from 'vuetify/lib'
and all the "VApp, VToolbarTitle, etc" I get the Unknown custom element message.
This line:
import Vuetify from 'vuetify/lib'
is how you import components a la carte.
If you instead want all of the components to be registered globally, import and install Vuetify like this:
import Vue from 'vue'
import Vuetify from 'vuetify' // omit /lib
Vue.use(Vuetify)

How to integrate sorting and pagination in angular2 rc5?

I am trying it integrate sorting and pagination in angular2 rc5. Pagination is working with ng2-pagination, searching for sorting. Any good example for sorting?
If anybody is still looking for answer (only for pagination), This link is a useful resource -
Implementing Pagination in angular2 > v.RC5
I integrated it within 5 minutes after I got above link.
In case - link is no longer available , here are the steps
app.module.ts
import {NgModule} from '#angular/core';
import {BrowserModule} from '#angular/platform-browser';
import {Ng2PaginationModule} from 'ng2-pagination'; // <-- import the module
imort {MyComponent} from './my.component';
#NgModule({
imports: [BrowserModule, Ng2PaginationModule], // <-- include it in your app module
declarations: [MyComponent],
bootstrap: [MyComponent]
})
export class MyAppModule {}
app.component.ts
import {Component} from '#angular/core';
#Component({
selector: 'my-component',
template: `
<ul>
<li *ngFor="let item of collection | paginate: { itemsPerPage: 10, currentPage: p }"> ... </li>
</ul>
<pagination-controls (pageChange)="p = $event"></pagination-controls>
`
})
export class MyComponent {
public collection: any[] = someArrayOfThings;
}
Therefor, For server side paging we can change this line of pagination-controls with replace some custom event -
This event (myCustomEvent($event)) must be defined and declared in component class or whatever you are going to use as a bootstrapper.
For sorting, excuse me for now.

Resources