Conditionally rendering the same component does not trigger mounted() hook - javascript

I'm pretty new to Vue so please correct me if my thinking process is wrong. I'm trying to conditionally render a component like this:
<div>
<Map v-if="bool" mapSrc="src1.jpg" :idList="idList1" :data="dataVariable1"></Map>
<Map v-else mapSrc="src2.jpg" :idList="idList2" :data="dataVariable2"></Map>
</div>
My goal here is to render the same component with different props depending on the v-if state. So when bool is true it should render the first component, and when i toggle bool to be false, it should render the second option. The props seems to be changing correctly, but when i toggle the bool state it does not seem to run the mounted() hook again, which is an indication that component1 does not seem to dismount, it just switches out the props basically.
What I want is that when bool is false, it should render a fresh version of that whole component instance, and be isolated of what previously was going on in component 1.
How can I achieve this?

according to Linus Borg's answer here, You should add a unique key attribute to both of them.

You can a achieve this by using key attribute
Specify different key for the 2 Map components.
<Map v-if="bool" mapSrc="src1.jpg" :idList="idList1" :data="dataVariable1" key="map1"></Map>
<Map v-else mapSrc="src2.jpg" :idList="idList2" :data="dataVariable2" key="map2"></Map>

Related

React: Hiding or Removing the component is more efficient?

I have three components in my app which are <Video />, <VideoPreview /> , <VideoWrapper />,
here VideoWrapper component conditionally renders other two components based on a state isDragging, whenever someone starts dragging it renders,
the code is like isDragging ? <VideoPreview /> : <Video />
Here in this question, I saw they prefer using the current (JSX short circuit rendering) approach. But in my case, the <Video /> component renders some other components, and it makes an HTTP request on every render to load the video from CDN.
So I'm confused about which one should be better, the current approach or passing the isDragging state to the video component and toggling the visibility using CSS when isDragging=true. Can anyone explain which one should be better?
You definitely want to drag the preview, and not the component itself. Depending on what you use for drag 'n drop, the dragged component could rerender multiple times during the full cycle.

How to get an value from Child component to Parent on nuxt.js?

I am stuck trying pass data from Child A ($emit) component to Parent and from Parent to Child B (props).
Using nuxt.js I have:
layouts/default.vue
This default template will load a lot of components.
Those components will be used or not based on variable from child, the variable will set the v-if directive.
The children are the pages like:
pages/blog/index.vue
pages/about/index.vue
...
The goal is the Child set on Parent what components would be used, the flag can change anytime, the user can choose what will be rendered on admin area.
I have tried use local computed methods on child component, and vuex, no luck with both.
The idea on layouts/default.vue.
<template>
<div>
<TopBar v-if=showTopBar></TopBar>
<Nav v-if=showNav></Nav>
etc...
<nuxt />
</div>
</template>
<script>
import TopBar from "../components/TopBar";
import Nav from "../components/Nav";
etc...
export default {
data() {
return {
showTopBar: false,
showNav: false
etc...
};
},
}
</script>
On child already have use the $emit but no luck.
Child on this situation are pages, and the layout of those pages will be defined by variable from a fetch on the API, user can change the layout anytime.
The goal is have someting like double way between Child Components, example:
Calling route /blog will call pages/blog/index.vue
This would send to layout/default.vue using $emit what components would be rendered (choosed from user in admin area and fetched from API) and the component ID. (example: {topBar: true, topBarID: 2})
On layouts/default.vue after get the $emit from pages/blog/index.vue I would have for example TopBar false, and then not render it, or have received true with an ID, this Id will be send to TopBar as prop for render the customized TopBar made by user on Admin area.
Would be possible someone show an example how to get the pass those data for this specific cenario please?
(Does not matter if using local variables from the Child component or vuex, just looking for an example how to get the contents of variable from Child instead an plain object or undefinied object).
PS.: If there an better approach to deal with dynamic layouts, I am accepting suggestions too.
PS2.: I know I would use specific template per page, like layout/blog and layout/contact, etc... but since the idea is make an CMS, this would not fit on this scenario, I mean, from the admin area user should be able to create pages enabling or disabling components through an page Wizard (the idea is getting something like Wix, every component customization from user will be stored in the database using an Id, and on layouts user choose the previous components mounting the page, in the end all call will be made using the ids of those), and not need to add specific layouts programing, because this the Idea of set all possible components and layouts in layout/default.vue sounds at this moment an better approach, but if is not, I would love see other ways to get same goal.
The correct way to do it would be:
<child-component-1 :showNav.sync="showNav">
And within the child component you would update that by doing:
this.$emit('update:showNav', value)
The parent would define this property:
data() {
return {
showNav: default_value
}
}
You would have to pass that variable to every child component. Every child component would have to define it as a property.
Perhaps a better way to do it would be to instead create a simple store within nuxt and use that to house the settings.

Mixing React Components with HTML Blocks

Something that's always confused me is how many React examples show everything as components. But's let's say I only need to include some simple HTML alongside my components, like:
class Homepage extends Component {
render() {
return (
<Container>
<Hero />
<Features />
<div className="copyright">Copyright Some Company Name.</div>
</Container>
);
}
}
The div element will never be more than static text.
Should the <div> be moved into a pure component? Or is it ok to simplify the Homepage component by adding plain HTML this?
Sure it's ok. all in all it's HTML in the end. React components are set of html elements when you call the render function.
One rule of thumb i follow is: create a new component when you think a new responsibility is in order.
That div is a component just like any other, except it is a "primitive" one. There should be no problem mixing the primitive components from HTML with your own custom components.

Keeping props bound when sending them in a click event in React.js

We have a component that is being sent to a function and then rendered elsewhere in react.js. This is for the ability to open a slider with given content. We give that child component the props from the parent and all is well when we first load of course, but we need to be watching for state changes. For example:
<Contact
handleNew={() => globalSlider.openContentSlider({
content: <PersonalContactDetail _flags={_flags} />
})}
/>
Of course the _flags is set appropriately on open, but the state changes do not cascade through.
Any ideas?
A property on the Contact component needs to be updated, otherwise it won't re-render (and therefore can't re-render your PersonalContactDetail). I don't know your architecture of course, but perhaps you can pass the _flags into your Contact component, and then pass them back into your handleNew() handler as an argument....
<Contact flags={_flags}
handleNew={(flagArgs) => globalSlider.openContentSlider({
content: <PersonalContactDetail _flags={flagArgs} />
})}
/>
... somewhere inside Contact:
if (this.props.handleNew) {
this.props.handleNew(this.props.flags);
}
try to pass an arrow function returning flags instead of returning the flags directly

Toggle state from another component

I'm pretty new to React and Redux so I may be doing this completely the wrong way, in fact judging from a few other answers to similar questions on here I suspect I'm doing quite a lot wrong.
I've got a button in my 'Layout' component which adds a class to a div, this class comes from a state. The button is a toggle and will turn the state & class on and off (this will result in making a menu appear and dimming the rest of the page).
However I also want any interaction with the 'Nav' component (which lives inside a 'Header' component which in turn lives in 'Layout') to also toggle the state & class (so clicking a link collapses the menu). In jQuery/VanillaJS this was incredibly easy but I can't seem to work out the React/Redux way of doing this.
Layout Component: https://pastebin.com/WzpbeSw7
Header Component: https://pastebin.com/c34NFtUx (probably not relevant but here for reference)
Nav Component: https://pastebin.com/EsJDuLQc
By using redux :
You can have a state like toggleBlaBla : "show" . If you connected your react component to state of redux by using react-redux , whenever you dispatch an action for changing toggleBlaBla to "hide", your connected component will rerender.
By using only react :
If you want two components to change some ui state by some events, it is a good idea to put them in a container component, so that whenever your state changes these two components rerender with your changed state passing to both components.
One way to achieve this is to do the following:
In Layout component:
On line 26 change <Header / > to: <Header handleNavClick={this.toggleNav.bind(this)} / >
In Header component:
On line 10 change <Navigation position="header" /> to: <Navigation closeNav={this.props.handleNavClick.bind(this)} position="header" />
In Navigation component:
On line 16 change return <li key={item._id}><Link to={item.slug}>{item.name}</Link></li> to: return <li key={item._id}><Link to={item.slug} onClick={this.props.closeNav.bind(this)}>{item.name}</Link></li>
Passing the props in this way will allow you to reference reference the toggleNav function inside of Layout and then will update the state accordingly.
*** Note, you may get a binding error such as React component methods may only be bound to the component instance..
If this happens, you will need to define a function on the Navigation component instead of using this.props.closeNav directly. You would need to create a function in Navigation like this: closeNav() { this.props.closeNav.bind(this) }. Don't forget to update the function on the <Link /> component to this.closeNav.bind(this)

Categories