Prism interactivity confirmation—callback or no callback? - wpf

When using InteractionRequest with Confirmation and synchronous Raise, there are two ways of getting the result of the confirmation. The most popular way seems to be:
Confirmation confirmation = new Confirmation()
{
Title = "Confirmation",
Content = "Do you really want to do this?"
};
DeleteConfirmationRequest.Raise(confirmation, c => {
if (c.Confirmed)
{
// do something terrible
}
});
However, since I don't really care in this case whether the user cancelled the request or didn't even subscribe to the confirmation, I can do this instead:
Confirmation confirmation = new Confirmation()
{
Title = "Confirmation",
Content = "Do you really want to do this?"
};
DeleteConfirmationRequest.Raise(confirmation);
if (confirmation.Confirmed)
{
// do something terrible
}
As far as I can tell, there is no real difference between these two. Am I right, or am I missing something here?

Do you mean synchronous = a PopupWindowAction with IsModal=true for example?
In this case, the variant without the callback is fine, I guess.
Although the callback-variant is safer if implementations change, and, for example, the action's Invoke doesn't block anymore or the Confirmation is cloned internally and the callback doesn't get the same instance you passed in...

Related

Whether it is good to do lot of functionality in the setState Callback?

I am trying to check and uncheck a checkbox based on other conditions in screen..
I am printing an element using document.getElementById('foo') this is returning null even my element is present in screen and in DOM.
Please help me to solve problem.
I am developing code in which after API is being fetched state variable need to be set and do other functionality based on the respective state variable.
Is it feasible to do most of the logic inside the call back of the setState to promote synchronus way of coding or any other concepts are present to do the same?
this.setState({
filter:filterValue
},function(){
// Most of the coding logic goes here
})
Please suggest a prominent way if it is wrong
Well you definitely shouldn't use document.getElementById since it's against reactive programming logic but it's hard to say where is a problem if you don't provide example code.
Try to implement checkbox in React way:
const CheckBoxComponent = (isChecked) => {
return <CheckBox checked={isChecked ? true : false}/>
}
then in your return:
<CheckBoxComponent isChecked={yourFunctionWhereYouResolveWheneverIsOrNotChecked}/>
Another point is that you really won't to hold logic in setState callback. I guess you are a beginner. You should get better knowledge of functional programming. It's easier than handling state logic and mutation.
Judjing from your question you want probably something like that:
const yourAsyncCallToApi = async() => {
await someApiCall()
yourFunctionWhereYouResolveWheneverIsOrNotChecked() //it will be called as soon as u got data from api call
}
const yourFunctionWhereYouResolveWheneverIsOrNotChecked = () => {
// handle your conditions and return false or true based on them
}

React - Old promise overwrites new result

I have a problem and I'm pretty sure I'm not the only one who ever had it... Although I tried to find a solution, I didin't really find something that fits my purpose.
I won't post much code, since its not really a code problem, but more a logic problem.
Imagine I have the following hook:
useEffect(() => {
fetchFromApi(props.match.params.id);
}, [props.match.params.id]);
Imagine the result of fetchFromApi is displayed in a simple table in the UI.
Now lets say the user clicks on an entity in the navigation, so the ID prop in the browser URL changes and the effect triggers, leading to an API call. Lets say the call with this specific ID takes 5 seconds.
During this 5 seconds, the user again clicks on an element in the navigation, so the hook triggers again. This time, the API call only takes 0,1 seconds. The result is immediatly displayed.
But the first call is still running. Once its finished, it overwrites the current result, what leads to wrong data being displayed in the wrong navigation section.
Is there a easy way to solve this? I know I can't cancel promises by default, but I also know that there are ways to achieve it...
Also, it could be possible that fetchFromApi is not a single API call, but instead multiple calls to multiple endpoints, so the whole thing could become really tricky...
Thanks for any help.
The solution to this is extremely simple, you just have to determine whether the response that you got was from the latest API call or not and only then except it. You can do it by storing a triggerTime in ref. If the API call has been triggered another time, the ref will store a different value, however the closure variable will hold the same previously set value and it mean that another API call has been triggered after this and so we don't need to accept the current result.
const timer = useRef(null);
useEffect(() => {
fetchFromApi(props.match.params.id, timer);
}, [props.match.params.id]);
function fetchFromApi(id, timer) {
timer.current = Date.now();
const triggerTime = timer.current;
fetch('path').then(() => {
if(timer.current == triggerTime) {
// process result here
// accept response and update state
}
})
}
Other ways to handle such scenarios to the cancel the previously pending API requests. IF you use Axios it provides you with cancelToken that you can use, and similarly you can cancel XMLHttpRequests too.

Is there a better way of updating the tx hash?

Following is a snippet of my code (which is working)
....
let txhash = '';
class App extends Component {
....
async componentDidMount() {
.....
}
onSubmit = async(event) => {
event.preventDefault();
const accounts = await web3.eth.getAccounts();
this.setState({
message: "Waiting for the transaction to be mined..."
});
await lottery.methods.enterLotteryContract().send({
from: accounts[0],
value: web3.utils.toWei(this.state.value, 'ether')
}).on('transactionHash', function(hash) {
txhash = hash
});
this.setState({
message: "Congrats, the tx has been mined; your txhash is " + txhash
})
console.log(txhash);
});
}
More over here: https://github.com/DKSukhani/lottery-react/blob/master/src/App.js
Was wondering if there is a better way for me to get the txhash and then display it. I was hoping that I could make txhash as one of the state components rather than declaring it as an empty variable. Also I am using the call back function in only reassigning it to txhash.
Can you ask your question a bit more clearly? Your code makes sense and looks fine for some unknown purpose. That purpose is exactly what I need to know though.
When do you need the txHash, is it after every call of this function or are you trying to track something else.
Why can't it be a state variable, you didn't include state in your snipped so I had to go look at the rest of your code and see no reason why not. You use it within the snippet so it's clear you can use it to some degree. I don't use React so maybe there's some render loop, listener issue, or other reason you can't use setState.
With that said, check out this link on the different events you can listen to with on, as I think you're listening to the wrong event or outputting the wrong text. When you set the state's message to say that the tx was mined I don't believe it actually has been.
I would use confirmation and only display the message on the first fire of the event, then ignore the remaining 23. The object returned alongside the confirmation number is described here and has a transactionHash variable you can use to both check that the transaction was confirmed and get the hash at the same time. Now your event call is no longer as wasteful and you can use the same setState call for the message as for the txHash, or even skip storing the txHash at all (as long as you can still use setState asynchronously).

Confirm box is blocking/pausing

I have a ng-click="myFunc(aEntry)"
And then myFunc is this:
MODULE.myFunc = function(aEntry) {
aEntry.hilite = true;
if (!confirm('Are you sure?')) {
aEntry.hilite = false;
return;
}
};
However it wont update the dom to show it highlighted. The confirm box seems to be pausing it. Does anyone know a work around?
It is because confirm is a blocking function. I understand you want to have a ui change, but
aEntry.hilite = true;
is not a UI change. It is a logical change. You probably have an event handler which runs after you have called confirm. You need to guarantee that the highlighting ui operation is performed before you call the confirm. There are several ways to do it.
The most primitive way is to use setTimeout and put your confirm call inside it, using a time, which is surely longer than the time you need to wait for the ui handler to be executed.
A slightly better approach is to use setInterval until the ui change has occured.
But the best approach would be to pass the confirm with a function wrapped around it used as a callback for the ui change or to trigger the ui change event before you call confirm.

Silverlight: stop thread while waiting for user feedback

Is it OK to stop current thread until user click some buttons in Silverlight? E.g.
var clicked = false;
ShowDialog(EventOnClosed => clicked = true);
while (!clicked) {};
return;
P.S. I know the right way. I'm just curious if there's a way to stop and then continue Silverlight execution flow.
P.P.S. Just to be more specific. Imagine a project where javascript alert() is used for messages. How do you replace "return Invoke("alert('')")" with Silverlight messageboxes? Do you change all 500 places to use the correct async technique?
No it isn't and you certainly won't want to tie up the CPU like that even if you do.
In Silverlight you really need to get used to programming in an asynchronous way.
void SomeContainingFunc(Action callBack)
{
ShowDialog(EventOnClosed => callBack()))
}
Whatever calls that and wants code to continue after the async operation is completed:-
void SomeCaller()
{
// ... do some intial stuff here
Action callBack = () =>
{
//.. code to happen after async call completed
}
SomeContainingFunc(callBack);
}
What you are attempting to do is halt (or more specifically pause) the UI thread - this is not a good idea in any circumstance, especially if you are waiting for the user to click something!
Just do it the "right way".

Resources