Vue child component not receiving prop from parent - vue.js

I have an Order form component which uses a OrderTasklistBuilder component. Note: there are nested components here. The hierarchy is as follows: OrderSingle > CreateOrderForm > OrderTasklistBuilder
The initial order is fetched when the OrderSingle is mounted and then passed down through child components.
The tasklist builder component is used like this:
<order-tasklist-builder v-if="form.tasks.length" :initial-tasks="form.tasks" #taskAdded="handleTaskAdded" class="mb-2" />
This works fine, but if there aren't any tasks in the listbuilder, the component will not display. This is a problem because someone might remove all of the tasks.
Now, if I remove the length check on form tasks the tasklist builder component will not display any tasks even after adding new tasks.
<order-tasklist-builder :initial-tasks="form.tasks" #taskAdded="handleTaskAdded" class="mb-2" />
The components are fairly large ( > 300 lines ) so if I can elaborate on something specific, let me know.

Solved by moving logic previously in mounted function inside of CreateOrderForm component to created function.

Related

Does react native always renders everything when state changes?

I would like to know if when a state changes only the component affected by the state and all its children are rendered or "the whole function (the return part) where that component is".
Example
const [label,setLabel]=useState();
...
export default function MyFunc(){
...
return (
...
(more than 200 rows of code)
...
(here i have the button)
...
(more then 200 rows of code)
)
}
When somewhere setLabel it's called, whenever it happens does React render everything included the other rows of code?
Yes. Whenever there is change in state react re-renders the component. That is the concept of react.
If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.
For more info, visit the below link,
https://reactjs.org/docs/react-api.html#reactmemo

Vue js - is that right to put all my code in watch?

I Have component A and Component B
in component A i have an API call.
when i passing info to my component b:
<B :structuresMetaData="structureTree"></B>
Inside mounted the variable structuresMetaData the length is 0
and inside the watch the length is 1.
my issue that mounted appear before the watch.
is it would be right to put all my code in watch ? if not what is the solution ?
It looks like structureTree is being changed after <B> is created/mounted.
You have two options depending on your use case:
The first option is to defer the creation of <B> until your data is loaded. This way you don't need <B> to watch for changes to the prop and the prop will be fully populated in the created/mounted hook. This is the simpler approach.
Assuming structureTree is initially an empty array:
<B
v-if="structureTree.length > 0"
:structuresMetaData="structureTree"
/>
created() {
// this.structuresMetaData is a non-empty array here
}
I usually initialize my data with null so that I can distinguish between "not loaded" and "loaded" (where "loaded" can actually be an empty array if the data I fetched from the API was empty).
The second way is using a watcher in <B> to react to changes to the prop. You will need to do this method if the bound prop might change multiple times and you need <B> to update in some way to that change.
watch: {
structuresMetaData(value) {
// React to the change, load secondary data, etc
}
}
What exactly are you doing in <B> that requires a watcher? It's best to avoid explicit watchers if you can avoid them because it usually means you are copying data around and it gets messy when you don't have a single source of truth. Use pure computed properties whenever you can if you just want to transform the data in some way.

Vue2 component as <vue-component>value</vue-component>

It is possible to pass a value to the component between the component tags?
Example: in a component to format value to money, I created as :
<vue-component value="50" />
and it display
$ 50,00
Now, just for curiosity, it is a way to call the component like these:
<vue-component>50</vue-component>
Read about slots: vuejs.org/v2/guide/components-slots.html
Fe: <template><h1><slot/></h1></template>
You can access ita value via: this.$slots.default[0].text
The fact that it's possible doesn't mean that you should do it. Actually, on the contrary. Props have multiple advantages (such as marking as required, default value, validators and many more) but in thr first place they are standardised way of passing data to children components every vuejs developer will understand.

vue.js dynamic component state

I have a multi-step layout managed with a dynamic component
<keep-alive>
<component :is="actualStep" :status.sync="status"></component>
</keep-alive>
<button #click.prevent="prevStep">Prev</button>
<button #click.prevent="nextStep" :disabled="!status">Next</button>
status value is used to monitor the actual component status, updating its value to true or false depending on component's internal validation process, and allowing (or not) to move to next step. As an example, a component will change status to true only if all required fields are filled.
status is also changed to an initial value when component is initiated. Some components change it to true (as they don't make any validation) and some change it to the validation process result.
mounted() {
this.$emit('update:status', this.isValid); // isValid is a computed
}
However this is only happening once when the component is mounted (I guess because of keep-alive). I would need to do this every time the dynamic component changes to the actualStep. How can this be done? or is it a better way to manage dynamic components' status?

VueJS Component Input Sync

I want to create components which have input which two-way bind to the local scope of the component.
Without a component, I would create a new Vue instance and then set my data to what I need. Then using v-model, bind an input to that data and it can be manipulated from the input.
However, converting the same code to a component, I cannot for the life of me get any input in a component to bind to its data. I have tried props, :data.sync, data attributes but no matter what I have tried, the input within a component does nothing.
I have created a JSFiddle to illustrate this:
https://fiddle.jshell.net/f0pdmLhy/2/
What I would like to happen is the input in the component to two way bind to the err variable, just like the non component version underneath.
How would I accomplish this?
I basically want to create components that I can instansiate with ajax data and then populate the inputs. The inputs could then update the data and I can use a save method to send the data to the server. Can this even be done using components?
So there are a couple of things:
The external resource you were using was somehow faulty. I've used
jsfiddle default Vue instance and it works fine.
When you declare a component, you should not define the data as an object, but as a function returning an object. Read here: https://vuejs.org/guide/components.html#Component-Option-Caveats
A working example here: https://fiddle.jshell.net/by4csn1b/1/
Yes, with components, the reactivity can be accomplished just like with an instance.
One catch with components, is that data must be a function that returns an object.
Also, to maintain the two way binding, use v-model in your input.
Vue.component('ii', {
template: '<span>{{err}}</span><input type="text" v-model="err"><hr>',
data: function () {
return {
err: 123
}
}
})
Fiddle: https://fiddle.jshell.net/f0pdmLhy/25/