I have prop in child component -> kpi_kalite[]
Parent component-> mounted():
*(This kpi_kalite is created in parent component's data)
axios.get(URL+ "/KPI/").then(response=>{
console.log(JSON.parse(JSON.stringify(response.data)))
this.kpi_kalite.push(response.data[0])
})
I do 'get request' in parent componenet and i push the response.data to kpi_kalite[] (parent component)
And i use this array for props.
Then, I want to do console.log(this.kpi_kalite) in beforeMount or Mounted.
But this props in not using.
methods : {
set_input(){
console.log(this.kpi_kalite)
for(const i in this.kpi_kalite){
console.log(i)
console.log(JSON.parse(JSON.stringify(this.kpi_kalite))) // output
// "undefined"
}
}
},
beforeMount() {
this.set_input()
}
console output : undefined
Could you help me? ,Before HTML-css loaded, I need parent component's data in child component
There is a post by LinusBorg about the order of lifecycle hooks for parent and child:
There’s nothing weird or wrong about it, it all follows from the
lifecylce logically.
beforeCreate() and created() of the parent run first.
Then the parent’s template is being rendered, which means the child components get created
so now the children’s beforeCreate() and created() hooks execute respecitvely.
these child components mount to DOM elements, which calls their beforeMount() and mounted() hooks
and only then, after the parent’s template has finished, can the parent be mounted to the DOM, so finally the parent’s beforeMount()
and mounted() hooks are called.
END
Also, there is a nice diagram here.
Child components are mounted before the parent component is mounted. Therefore, console.log(this.kpi_kalite) in the child component does not print the data gotten from the axios in the parent. So, if you do not render the child component at first, it will not be mounted because it is not created. If you render the child component after the axios is completed, it will be created and mounted. Then, console.log will print the value of kpi_kalite gotten from the axios in the parent.
ParentComponent:
<ChildComponent v-if="renderChildComponent" :kpi_kalite="kpi_kalite" />
data() {
return {
kpi_kalite: [],
renderChildComponent: false,
};
},
mounted() {
axios.get(URL+ "/KPI/").then(response=>{
console.log(JSON.parse(JSON.stringify(response.data)))
this.kpi_kalite.push(response.data[0])
this.renderChildComponent = true;
})
},
Related
I have a child component SecondPage.vue. Props are passed to this component from parent component. Props are passed to child on click event. Then I'm trying to copy these props to data in SecondPage.vue. But when I use vue devtools, I can see, that data in child component is clear.
According to devtools, after click props in child are provided, but data (genQ, isA) is empty.
Where is the mistake?
SecondPage.vue
export default {
name: "SecondPage",
props: ["generalQuestInfo", "isActive", "getIconClass"],
data: function(){
return {
genQ: Object.assign({}, this.generalQuestInfo), //empty in devtools
isA: this.isActive //empty in devtools
}
}
}
Vuex store solved my problem!!!
how to force render our component when props changes?
how to force render parent component when child component's props changes?
i searched a lot but all solutions are deprecated in new React version.
in my any pages (Route exact path="/post/:id" component={post}) for example (siteUrl/post/1) i am getting (:id) from props (this.props.match.params) and that works.
but when i am in single page component (Post) and this Route (siteUrl/post/1) when i am passing new Props to this component (:id).
props will changes but single component and parent component Will not re render...
You may be using componentDidMount method.
componentDidMount() is invoked immediately after a component is
mounted (inserted into the tree). Initialization that requires DOM
nodes should go here. If you need to load data from a remote endpoint,
this is a good place to instantiate the network request.
but you need to use componentDidUpdate.
componentDidUpdate() is invoked immediately after updating occurs.
This method is not called for the initial render.
You can also use state and other React features without writing a class.
read more: https://reactjs.org/docs/hooks-effect.html
To make both parent and child re-render you need to path prop from parent to it's child.
// parent using
<Parent someProp={{someVal}} />
// parent render:
render() {
const { someProp } = this.props
<Child someProp={{someProp}} />
}
this will surely re-render both components, unless you stated another logic in componentShouldUpdate
in your case Router looks like a parent for Parent so you should only path :id as a prop.
Make sure Router is at the top level, right under the App
Important is ,that you initialise the someVal of the child first in the constructor
public static getDerivedStateFromProps(
nextProps,
nextState
) {
let { someVal } = nextProps;
if (nextState.someVal !== someVal) {
return {
initialVal,
someVal: someVal
};
}
return null;
}
After it will rerender on prop changes because the state changes
I am making a form built of Vue JS components. I have the following components tree (each component contains the child below it ex. User Registration Form has the Form component as its direct child).
User Registration Vue Component
Form Vue Component
Input Vue Component
Input Option Component
After all of the components have full rendered I need to run a function in the User Registration. I tried putting it in the mounted function in the User Registration Vue Component but it runs before the Option Components have completed their mounted function.
I read here: https://medium.com/#brockreece/vue-parent-and-child-lifecycle-hooks-5d6236bd561f that this should not happen and that the child component should be completely mounted before the running the parent mounted function, in this situation the User Registration Vue Component.
I have about 100 components total including the Form, Inputs and all of the options.
I can only run this desired code in the User Registration Vue Component after everything has fully rendered and loaded. I tried using the jQuery(document).ready function but I have inconsistent results (sometimes the document is ready before the forms have fully mounted).
Any recommendations?
If you need to know when a component has been created, mounted, updated etc. from a parent component, you can just define a listener using #hook: followed by the lifecycle hook name.
E.g. from the parent component to execute doSomething() once the child component is mounted:
<child-component #hook:mounted="doSomething" />
Since the child mounting could be delayed more that nextTick(), you can emit an event programatically:
Child JS:
{
mounted: function() {
this.$emit("mounted");
}
}
Parent HTML:
<child #mounted="childMounted">
Parent JS:
{
methods: {
childMounted: function() {
// TODO child action
}
}
}
An alternative is to use the child component as a mixin
Define a directive:
Vue.directive("mounted", {
inserted: function(el, binding) {
binding.value();
}
});
You don't need to modify the child, only the parent:
Parent HTML:
<child v-mounted="childMounted">
Parent JS same as in (2)
mounted() hook of the parent component does not guarantee that all child component also finish rendering.
To execute something once the whole view has been rendered use vm.nextTick() inside the the parent component's mounted() hook.
//User Registration Vue Component
mounted(){
this.$nextTick(()=>{
//execute your code
console.log('Finished rendering the complete view')
})
}
Refer to - mounted lifecycle hook
Thanks #Tires, it works well
Vue.directive("mounted", {
inserted: function(el, binding) {
binding.value();
}
});
Parent:
<child v-mounted="childMounted">
{
methods: {
childMounted: function() {
// TODO child action
}
}
}
I'm trying to create a wrapper that does not mount the child if the user is not authenticated. Otherwise, it mounts and renders the child component.
Roughly looks like this:
export class RedirectOnCondition extends Component {
render(){
return this.props.isAuthenticated? this.props.children : null
}
}
My issue is the the child still mounts before the parent has a chance to evaluate the condition. It's only after the child's componentWillMount` (and any associated API calls have fired and failed) that the parent's render kicks in and remove's the child. According to this question this is how React works.
How can I get around this?
In the first render, the parent component may have not yet received the props you need to process the conditional rendering of a children component. In this case, you may want to check first if the props is already there.
export class RedirectOnCondition extends Component {
render(){
return "isAuthenticated" in this.props ? this.props.isAuthenticated? this.props.children : null : null
}
}
Right now I have a sidebar that I want to use for various forms and bits of information. I'm using the global event system to trigger the opening of the sidebar, but I'm not sure how to inject react components into the sidebar react component.
I started by trying this
componentWillMount: ->
window.toggleSidebar = (react_component)=>
React.renderComponent(react_component(), document.getElementById('sidebar-content'))
#toggleSidebar()
But this didn't work once all of the components are mounted because you can't call render component into an element that is inside another component.
So is there an accepted way to pass any react component into another component?
You don't actually want to pass a component instance, you want to pass the component factory and data that it can use to render the component.
events.emit('sidebar-change-request', {component: Foo, props: obj, open: true});
And in the sidebar component it'd be listening to the event:
getInitialState: -> component: React.DOM.div, props: {}, open: false
# standard event emitter stuff
componentDidMount: ->
events.addListener 'sidebar-change-request', this.handleSidebarChangeRequest
componentWillUnmount: ->
events.removeListener 'sidebar-change-request', this.handleSidebarChangeRequest
# simply apply the payload to state
handleSidebarChangeRequest: (payload) ->
this.setState payload
# dynamically render stuff
render: ->
if this.state.open
React.DOM.div {className: "sidebar"},
this.state.component this.state.props
else
React.DOM.div null
If you needed to get some information back from the component renered in the sidebar, you'd pass a callback to that components via props; or the component could emit events.