Redirect using history in actioncreator and react-router v.4 - react-router-v4

I'm trying to navigate programmatically in action creator after calling an API and receiving a response.
What I did:
I created a file utils/History.js with this code:
import createBrowserHistory from 'history/createBrowserHistory';
export default createBrowserHistory();
and then used it in action creator:
import History from '../../utils/History';
//some code
History.replace('/sign-in');
Of course, I let relevant component know about this routing. If I use <NavLink to='/sign-in'>, it works. But if I want to render this component on History.replace('/sign-in') or History.push('/sign-in'), I can see just 'localhost:8080/sign-in' in address bar, but relevant component doesn't appear.
Please help me to figure out.

The simplest way would be to create a history.js file:
import createHistory from 'history/createBrowserHistory';
export default createHistory();
And then, in your action.js (or actions/index.js, whatever you prefer):
import history from './history';
history.push('/your_route');

Related

How to override cx-item-counter in spartacus

I am trying to customize the product increment or decrement quantity from OOTB to have my own implementation. Below is the screenshot.
I tried to create a new component in my custom store and used the extend feature of angular as this is not a cms component.
My Custom component is not getting rendered instead it renders the cx-item-counter.
import { ItemCounterComponent } from '#spartacus/storefront';
import {
Component,
OnDestroy,
OnInit,
} from '#angular/core';
#Component({
selector: 'custom-item-counter',
templateUrl: './cart-counter.component.html',
export class CartCounter extends ItemCounterComponent {
}
Is there any way I can achieve to override this?
Firstly, have a look at how the component is setup in the official spartacus repo:
https://github.com/SAP/spartacus/tree/release/4.0.0/projects/storefrontlib/src/shared/components/item-counter
I imagine you would need to create a module and have the module import the component. To render your custom version, you would need to use in the component that you import your custom component in.
Wherever you want your custom module/component to be imported, replace ItemCounterModule.
Currently the add to cart component imports it directly:
https://github.com/SAP/spartacus/tree/release/4.0.0/projects/storefrontlib/src/cms-components/cart/add-to-cart
If you are not overriding the add to cart component, then I am not sure you can achieve what you are looking to achieve, since the spartacus version of the item counter is being imported directly. You might need to extend the add to cart component as well so that you can change to .
This would be my approach. I have not tested it. Perhaps this at least points you in the right direction.

Calendly widget doesn't work after page refresh when live

The calendly widget works at first, but if you refresh the page it stops working but only when the website is live. In local development, no such issue occurs.
Also noticed that when I route to the page through navigation, it works. But if I enter the link to the specific page directly, it doesn't work.
Here's the code:
<template>
<client-only>
<vue-calendly url="link" :height="650"></vue-calendly>
</client-only>
</template>
<script>
import Vue from 'vue';
export default {
created() {
if (process.isClient) {
const VueCalendly = require('vue-calendly').default;
Vue.use(VueCalendly);
}
}
};
</script>
The Vue application is running on Gridsome so it's SSR. I set the widget to only display in client side. Not sure what the issue is.
There is a solution possible to integrate Calendly without using their widget. You can try it as well. This solution should not produce the error mentioned and was tried in an SSR application.
<template>
<!-- Calendly inline widget begin -->
<div class="calendly-inline-widget" data-url="YOUR_CALENDLY_URL" style="min-width:320px;height:630px;"></div>
<!-- Calendly inline widget end -->
</template>
<script>
export default {
mounted () {
const recaptchaScript = document.createElement('script')
recaptchaScript.setAttribute('src', 'https://assets.calendly.com/assets/external/widget.js')
document.head.appendChild(recaptchaScript)
}
}
</script>
From this link, we can see that he is importing the component with
import Vue from 'vue';
import VueCalendly from 'vue-calendly';
Vue.use(VueCalendly);
Then with
<vue-calendly url="your Calendly URL" :height="600"></vue-calendly>
I'm not sure if you are trying to use a syntax like es2020 import here but the require('vue-calendly').default is probably the issue here.
Try importing it in the basic way as suggested above, and then you will be able to make some lazy-loading of it later on if you wish.
Also, you may use your devtools to see why your Calendly instance is not present.
Addy Osmani did a great article on how to import on interaction if you're interested into optimizing your loading time. If it's not that much needed, simply use the usual method or even simpler, load the vanilla JS solution.

Call component from another component

https://imgur.com/quHp4ym
This is my Folder structure.
I want to call Login Component from AppHeader Component. What will be the folder structure during calling.
My try:
Not working.
<script>
import Login from '../components/auth/Login.vue'
export default
{
}
</script>
You should accomplish it with
import Login from '../../auth/Login'
Use # prefix to point to root folder of project then you can go anywhere
import Login from '#/...';

In Vue.js why do we have to export components after importing them?

In PHP when we include code from another file, we include it and that's it, the code is now available to us within the file in which we performed the include. But in Vue.js, after importing a component we must also export it.
Why? Why don't we simply import it?
in Vue.js, after importing a component we must also export it.
I think you might be referring to the following lines in User.vue and wondering why UserDetail and UserEdit are imported into the file and then exported in the script export's components property:
import UserDetail from './UserDetail.vue';
import UserEdit from './UserEdit.vue';
export default {
components: {
appUserDetail: UserDetail,
appUserEdit: UserEdit
}
}
vue-loader expects the script export of a .vue file to contain the component's definition, which effectively includes a recipe to assemble the component's template. If the template contained other Vue components, the definition of the other components would need to be provided, otherwise known as component registration. As #Sumurai8 indicated, the import of the .vue files itself does not register the corresponding single-file-components; rather those components must be explicitly registered in the importer's components property.
For example, if App.vue's template contained <user /> and User.vue were defined as:
<template>
<div class="user">
<app-user-edit></app-user-edit>
<app-user-detail></app-user-detail>
</div>
</template>
<script>
export default {
name: 'user'
}
</script>
...the User component would be rendered blank, and you would see the following console errors:
[Vue warn]: Unknown custom element: <app-user-edit> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
[Vue warn]: Unknown custom element: <app-user-detail> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
demo 1
When Vue attempts to render <user /> inside App.vue's template, Vue doesn't know how to resolve the inner <app-user-detail> and <app-user-edit> because their component registrations are missing. The errors can be resolved by local component registration in User.vue (i.e., the components property shown above).
Alternatively, the errors can be resolved with global component registration of UserDetail and UserEdit, which would obviate the local registration in User.vue. Note that global registration must be done before creating the Vue instance. Example:
// main.js
import Vue from 'vue';
import UserDetail from '#/components/UserDetail.vue';
import UserEdit from '#/components/UserEdit.vue';
Vue.component('app-user-detail', UserDetail);
Vue.component('app-user-edit', UserEdit);
new Vue(...);
demo 2
Components in vue can be tricky. If you haven't yet, I would highly recommend reading the documentation on the vue.js website on how component registration works, specifically, as tony19 mentions global and local registration. The code example you show in your screenshot is actually doing a couple of things. For one, it is making the components available locally, and only locally (as in that .vue file) for use. In addition, it is making it available to the template as the key you provide in the components object, in this case, app-user-detail and app-user-edit instead of user-detail and user-edit.
Importantly, it should be mentioned that an import is not actually required for this component registration to function. You could have multiple components defined in a single file. The components key gives a way to identify what that component is using. So that import isn't required, so vue does require the components key to understand what you are using as a component, and what is just other code.
Finally, as some of the other answers have alluded to, the components key is not actually an export. The default signature of a vue component requires an export but this is not exporting the components listed under the components key. What it is doing is letting vue build in a top down manner. Depending on what the rest of your application setup looks like, you may be using single file components, or not. Either way, vue will start with the top level vue instance and work its way down through components, with the exception of global registration, no top level component knows which components are being used below it.
This means for vue to render things properly, each component has to include a reference to the extra components it uses. This reference is exported as part of the higher level component (in your case User.vue), but is not the component itself (UserDetail.vue).
So it may appear that vue requires a second export after import, but it is actually doing something else to allow the root vue instance to render your component.
As an aside, the vue documentation on this subject really is quite good, if you haven't already please take a look at the sections I linked above. There is an additional section on module import/export systems that seems highly relevant to what you are asking, you can find that here: Module-systems.
import imports code into the current file, but it does not do anything on its own. Imagine the following non-vue code:
// File helpers.js
export function tickle(target) {
console.log(`You tickle ${target}`)
}
// File main.js
import { tickle } from 'helpers'
You have imported the code, but it does not do anything. To actually tickle something, you need to call the function.
tickle('polar bear');
In Vue this works the same. You define a component (or actually just an Object), but the component does not do anything on it's own. You export this component so you can import it in other places where the Vue library can do something with this object.
In a Vue component you export your current component, and import components you use in your template. You generally do the following:
<template>
<div class="my-component">
<custom-button color="red" value="Don't click me" #click="tickle" />
</div>
</template>
<script>
import CustomButton from './CustomButton';
export default {
name: 'my-component',
components: {
CustomButton
}
}
</script>
Your component mentions a component named "custom-button". This is not a normal html element. It does not know what to do with it normally. So what do we do? We import it, then put it in components. This maps the name CustomButton to the component you imported. It now knows how to render the component.
The "magic" happens when you mount the root component using Vue, usually in your main.js.
import Vue from "vue";
import App from "./App";
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: "#app",
components: { App },
template: "<App/>"
});
What does this do? You tell Vue to render <App/> in a html element identified by #app, and you tell that it should find this element in ./App.vue.
But can't we just omit export if the Vue compiler was 'smarter'? Yes, and no. Yes, because a compiler can transform a lot of things into valid javascript, and no because it makes no sense and severely limits what you can do with your component, while also making the compiler more bug-prone, less understandable and overall less useful.
In order for App.vue to be able to use the User-component you need to export the default object of the User.vue-file.
In the export default { you don't actually export the newly imported components. You are just exporting a completely normal JavaScript Object. This object just happens to have a reference to another Object.
When you import an object (or function or array or ...) it does not actually load the content of that file in to your component like PHP. It simply makes sure that your compiler (probably webpack) knows how to structure the program. It basically creates a reference so webpack knows where to look for functionality.
TL;DR
The import and export here are conceptually different and unrelated things, and both have to be used.
Importing a Vue component is the same with any other importing in JavaScript:
// foo.mjs
export function hello() {
return "hello world!";
}
// bar.mjs
import { hello } from './foo.mjs';
console.log(hello());
Now run node bar.mjs, you will get a feeling how the importing works -- you want to use something that is defined/implemented somewhere else, then you have to import it, regardless of whether it is a Vue component or not.
With regard to export, you are not exporting the components you imported. The only thing you are exporting is the current component. However, this current component may use some other subcomponents in its <template>, so one has to register those subcomponents, by specifying them in the components field in the exported object.

React Native navigation actions

I have problem about navigation from other script (screen)... I implemented navigation in App.js (with createStackNavigator and with screens). Everything works fine when I want to navigate (with OnPress{() => navigate("someScreen")} to screen which is defined in this script (App.js).
But, when I want to use that navigation from other script (outside of App.js), let's say in "NewPage.js"
which has own "export default class NewPage..." and inside I have button element which task is to navigate "onPress" to screen which is defined in the App.js stackNavigator...
I know that I can't use anymore navigate("pageName") because navigation isn't implemented in this script and I tried with import { NavigationActions } from 'react-native' and inside of button element I tried with code: "this.props.navigation.navigate('somePage')" and it's not working.
So I don't know how to use navigation property from other script in which isn't implemented navigation, how to reference/export/import that property?
Here is code App.js script: https://pastebin.com/tLEFdQrE and NewPage.js script: https://pastebin.com/aVQGiinJ
This code is short so you can easily see what I want and what is the problem...
Thank you in advance!
Use this for better navigation among screen as compared to default navigation this is the better one for navigating among the screens. We mostly use this than other navigator
https://github.com/aksonov/react-native-router-flux
You should import your pages [using the names of the exported components, not the names of the js files] into your App.js.
For example, I stored my pages in a folder called 'screens' so when I imported my 'Home' screen, I used
import HomeScreen from './screens/HomeScreen.js';
which was further referenced as
Home: HomeScreen,
Good luck!