In this PlunkerDemo, I'm trying to broadcast an event from the parent controller to child controller. However doing it directly in the parent controller won't work. The handler doesn't register the event. However doing it based on an ng-click or based on setTimeout, it works. Is it due to the scope life cycle?
http://beta.plnkr.co/edit/ZU0XNK?p=preview
See the comments of the accepted answer. They explain my problem.
Any changes to angular scope must happen within the angular framework, If any changes have to be made outside the framework we have to use the .$apply function.
$apply() is used to execute an expression in angular from outside of
the angular framework.
In your case you are triggering the $broadcast within setTimeout, where the callback gets called outside the angular framework.
So you have two solutions, either use the $timeout service provided by angular or use .$apply function.
I prefer to use the $timeout function.
var ParentCtrl = function($scope, $rootScope, $timeout){
$scope.broadcast = function(){
$rootScope.$broadcast('Sup', 'Here is a parameter');
};
$timeout(function(){
$scope.$broadcast('Sup');
}, 1000);
//this one does not work! Most likely due to scope life cycle
$scope.$broadcast('Sup');
$scope.$on('SupAgain', function(){
console.log('SupAgain got handled!');
});
};
Demo: Fiddle
Using $apply
setTimeout(function(){
$scope.$apply(function(){
$scope.$broadcast('Sup');
});
}, 1000);
A more reliable option can be to use $interval in child controller. So, instead of having significant timeout, there will be polling every small interval.
Also, instead of broadcast, use a service with a flag. Every poll will check if flag is set. When the flag is set by parent controller, the timer will be stopped during next poll. And that can indicate the event happened. The parent controller can also share data with child controller, via service.
Related
I've a drop down on select the saga is called and the same component must be used. The sagas are called the only thing not happening is the set state is updating before the saga call therefore the component never updates the data.
recievedChangeValue=(selectVal)=>{
console.log(selectVal)
if(selectVal==='Yearly'){
this.props.getYearlySales() **//call to saga**
this.setState({salesData:this.props.yearlySales}) **//it updates before the called saga ends**
}
if(selectVal==='Decade'){
this.props.getSales()**//call to saga**
this.setState({salesData:this.props.dataSales}) **//it updates before the called saga ends**
}
}
I know the callback but here the state must be updated only after the saga call.I'm working onto it since past day I've no idea as to what has to be done. Any help is appreciated.Please lemme know as to where i'm going wrong.
You can't wait in component for the saga to finish, because this.props.getSales isn't really calling a saga - it is just dispatching an action.
When an action is dispatched something can happen in your app based on that, but the way the pattern works is that the "dispatcher" doesn't know about any of that.
The only common way saga can communicate with components is through changing redux state. So instead of changing local state in the callback you will have to wait for the dateSales prop to change and then update the local state using getDerivedStateFromProps.
static getDerivedStateFromProps(props) {
return {salesData: props.dataSales}
}
For more info on using getDerivedStateFromProps see
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#fetching-external-data-when-props-change
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#when-to-use-derived-state
https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops
recievedChangeValue=(selectVal)=>{
this.setState({selectedSalesData:selectVal},
()=>{
if(selectVal==='Yearly'){
this.props.getYearlySales()
}
if(selectVal==='Decade'){
this.props.getSales()
}
}
)
}
The following I wrote in render
let SalesData=this.handleSalesData(selectedSalesData)//calls on selecteddata and it works like a charm
When my component mount I need to request it content from an API. In the docs:
componentDidMount() is invoked immediately after a component is
mounted. 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.
and it follows:
Calling setState() in this method will trigger an extra rendering (...)
Use this pattern with caution
because it often causes performance issues.
What is the best practice to make a request to an API and, immediately, setState with the response?
The best way to call an API and update the state after you receive the response is in componentDidMount() or componentWillMount().
Which one might depend on what you want to do with your data from your API-call. If you need to access your components DOM then componentDidMount() must be used. That said, neither of these will save you from an additional re-render, unless your data doesn't need to be set to your state, in which case you can just save it to this.
The official documentation even states this, in this section:
componentDidMount() is invoked immediately after a component is mounted. 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.
Before Rendering to call api:
componentWillMount(){
fetch(api)
.then((response)=>{
this.setState({data:response.data});
})
}
After Rendering to call api:
componentDidMount(){
fetch(api)
.then((response)=>{
this.setState({data:response.data});
})}
Before Rendering to call props data:
componentWillReceiveProps(){
this.setState({data:this.props.data});
}
Whenever you trigger setState your component is going to be re-rendered (regardless the lifecycle event).
Use this pattern with caution...
You can get to an endless loop for example if you trigger setState in componentWillReceiveProps and you are not taking care of future props correctly.
My suggestion is to stick with componentDidMount and set state as soon as your api request is fulfilled:
componentDidMount() {
fetch('api-endpoint')
.then(response => response.json())
.then(result => this.setState({ stateProp: result }))
}
I just have implemented AJAX calls using fetch in react-native.
Implementing queuing of these AJAX calls hasn't been very well implemented.
Can any one help me?
If you want to make parallel requests, you can use the fact that fetch returns a promise to you, and then you can use Promise.all to wait for completion of all promises.
For example:
var urls = ['http://url1.net', 'http://url2.net'];
var requests = [];
urls.forEach((url)=>{
request = fetch(url); // You can also pass options or any other parameters
requests.push(request);
});
// Then, wait for all Promises to finish. They will run in parallel
Promise.all(requests).then((results) => {
// Results will hold an array with the results of each promise.
}).catch((err)=>{
// Promise.all implements a fail-fast mechanism. If a request fails, the catch method will be called immediately
});
I noticed that you added the 'multithreading' tag. It is important to notice that this code won't be doing any threading for you, as JS (generally) runs in only one thread.
Earlier I used to show a loader before ajax calls start and remove the loader once the call is completed. Now I have two calls in one single page. In this scenario how should I handle the loader ? If I use the same approach as earlier even though other call is not finished loader would be removed
You can use angular $q service which allows to wait a group of multiple promises to be resolved.
Example :
$q.all( [promise1, promise2] ).then(() => {
// only when both are resolved
// so here you can remove the loader
});
I m developping a Winjs/HTML windows Store application .
I have to do some tests every period of time so let's me explain my need.
when i navigate to my specific page , I have to test (without a specific time in advance=loop)
So when my condition is verified it Will render a Flyout(Popup) and then exit from the Promise. (Set time out need a specific time but i need to verify periodically )
I read the msdn but i can't fullfill this goal .
If someone has an idea how to do it , i will be thankful.
Every help will be appreciated.
setInterval can be used.
var timerId = setInternal(function ()
{
// do you work.
}, 2000); // timer event every 2s
// invoke this when timer needs to be stopped or you move out of the page; that is unload() method
clearInternal(timerId);
Instead of polling at specific intervals, you should check if you can't adapt your code to use events or databinding instead.
In WinJS you can use databinding to bind input values to a view model and then check in its setter functions if your condition has been fulfilled.
Generally speaking, setInterval et al should be avoided for anything that's not really time-related domain logic (clocks, countdowns, timeouts or such). Of course there are situations when there's no other way (like polling remote services), so this may not apply to your situation at hand.