Is there any difference between using React's setState() method in the following two ways:
setState({key: value}, myFunction())
vs.
setState({key: value}, () => myFunction())
(edited to use myFunction as in the post).
The two lines of code are quite different:
setState({key: value}, myFunction())
calls myFunction when the arguments are being evaluated, before calling setState. The return value of myFunction is then passed to setState as its second argument. So this version is only useful if myFunction() returns a callback function for use by setState. If myFunction is the callback, however, then it's a bug which could manifest itself as the callback being called prior to the state being updated instead of afterwards.
setState({key: value}, () => myFunction())
creates an anonymous call back function which when executed returns the return value of calling myFunction. The arrow callback function is passed as the second argument to setState, without calling myFunction in the process. myFunction will then be called after setState has updated the state and called the arrow function.
The second form is generally better written without creating an anonymous function intermediary:
setState({key: value}, myFunction)
Although possibly unrelated to the question, an arrow function could be used to set the this value of myFunction to the this value prior to the call to setState:
setState({key: value}, ()=>this.myFunction); // use current this value in the callback.
Related
Let's say you have a method/function which you did not want to call until runtime.
const someMethod = () => {
document.getElementById("myField").value = "Hello";
}
What is the term for and what is the difference between how these are executed.
this.check(() => someMethod);
AND
this.check(someMethod())
They're entirely different.
this.check(() => someMethod); will pass a callback which, when called (if ever), returns a function.
this.check(someMethod()) will call someMethod immediately, then pass the result to the this.check method.
Another option not listed is this.check(() => someMethod());, which will call someMethod when the callback passed to check is called.
If the this context is something you're worried about, then:
this.check(someObj.someMethod)
will result in someMethod, when invoked, to be invoked with a this of whatever the check method wants it to be. It does not preserve the context of someObj. In contrast
this.check(() => someObj.someMethod())
will result in someMethod being invoked with a this of someObj, regardless of how check tries to call it.
So, usually, to be safe, you'll want this.check(() => someObj.someMethod()) - or bind someMethod in advance, or declare someMethod with an arrow function instead of a function.
Here: this.check receives a callback as its paramter which returns the someMethod function.
this.check(() => someMethod);
And in this case: this.check receives the value that someMethod returns as its parameter.
this.check(someMethod())
Sorry if the title isn't clear but I don't know the correct terminology, so basically what is the difference between this:
doSomething(servletPath,
function () {
checkErrors();
}, function () {
init();
}, function () {
showErrorMsj();
}
);
And this:
doSomething(servletPath, checkErrors, init, showErrorMsj);
Both seem to work the same on an old legacy project I am maintaining but I would like to know if one is preferred to the other and why.
The only difference is in the parameters and this context. If the functions don't accept any parameters, or if the doSomething doesn't pass any parameters, the code is equivalent.
If, say, checkErrors did accept a parameter, and doSomething calls the functions with parameters, then doing
function () {
checkErrors();
},
instead of
checkErrors,
would result in checkErrors being called with no arguments, instead of with whatever argument(s) the doSomething passed.
On a similar note, the
function () {
checkErrors();
},
will call checkErrors with no calling context (the this inside it will be either the global object or undefined). But if you do
checkErrors,
then the doSomething will have the ability to call it with a different calling context. (It won't necessarily do so, but it would be doable)
const getData = (cb) => {
setTimeout( () => {
cb({ data: ['there', 'is', 'stuff', 'here'] })
}, 100)
}
getData( data => {
console.log(data);
});
Here is the example of the javascript callback. Could some one let me know how this functions is executed into the javascript callback?
Here what is the function inside getData(cb) ? How it will be executed ? How the functions is passed as callback inside cb and return to the console.log
Regards.
The function inside getData is a callback being passed to setTimeout, which is one way to schedule a call to a function to happen in the future. In this case, it's asking for that callback to happen roughly 100ms later. getData returns before that happens.
The setTimeout callback is a closure¹ over the context where it's created, which means it has access to cb even after getData has returned. So when the browser's timer calls the callback, the callback can call cb. The call to cb uses an object literal to create an object to pass to cb.
In the call to getData, the author is passing a function as cb that logs the data it receives.
So:
getData is called, passing in a function that will log the argument it gets.
getData calls setTimeout to schedule a callback in about 100ms, passing in another function for the timer to call.
getData returns.
About 100ms later, the browser's timer subsystem triggers a call to the callback passed to setTimeout.
That callback creates an object and calls cb, passing the object to it.
That callback (the one passed to getData) logs the data object it receives.
¹ "closure" — see: SO, my anemic blog
In order to understand the code you can just simplify it by naming the anonymous functions. One example could be:
function logData(data) {
console.log(data);
}
const getData = (cb) => {
// `cb` is `logData` function when `getData` is called
function timeoutCallback() {
var data = { data: ['there', 'is', 'stuff', 'here'] };
cb(data);
}
setTimeout(timeoutCallback, 100)
}
getData(logData);
Does that make sense?
1- first global execution context created
2- get data function will be called then it will wait for 10 seconds inside the event loop then it will be come to execution context and printed to console.
RxJS has a nifty function, fromCallback that takes a function whose last parameter is a callback and returns an Observable. And I want to combine that with React's setState function so that I can do something analogous to:
const setState = Rx.Observable.fromCallback(this.setState);
setState({ myState: 'Hi there!' }).concat(....)
so that any operations chained to setState are guaranteed to happen after the state has been set and, most importantly, that setState isn't invoked until there's an active subscriber.
What I noticed though is that even without a subscribe, setState is being called right as it's defined and setting the state of my component. So if I have:
networkSignal.flatMap((x) => {
return setState({ myState: 'test' });
});
the function setState is immediately invoked but the observer it producers won't send a next until there's a subscriber. What I want is for the function to only invoke when there's a subscriber.
Looking into the source you can see that RxJS returns a function that when executed, creates an observable but immediately invokes the function - the callback argument.
fromCallback returns a function which, when executed, returns an observable. That observable is where the asynchronous result(s) of the function call will flow.
To delay the execution of the function, you can make use of .defer. For instance:
const setState = Rx.Observable.fromCallback(this.setState);
const deferred$ = Rx.Observable.defer(function (){return setState({ myState: 'Hi there!' }).concat(....)});
// Later on
deferred$.subscribe(...)
Question whose answers used the same technique were asked here and here
This is my piece of code, which works correctly (adds records), but throws an error after addition:
Uncaught Error: Invariant Violation: enqueueCallback(...): You called
setProps, replaceProps, setState, replaceState, or
forceUpdate with a callback that isn't callable.
handleSubmit: function(e) {
e.preventDefault();
return $.post('', {page: this.state},
function(data) {
this.props.handleNewPage(data);
return this.setState(this.getInitialState(), 'JSON');
}.bind(this)
);
}
There are no routes for now. Can someone help me to solve this?
The second (optional) parameter to setState is a callback function, not a string. You can pass a function that will be executed once the operation is completed.
You actually invoke getInitialState instead of providing a reference to the function itself on the line return this.setState(this.getInitialState(), 'JSON'); and the second argument should never be anything but a callback function.
this.setState expects either a function that should return a state object as a single argument, or an object to merge the current state with (plus optionally a callback as a second argument to run after state has been set). So either you provide just a function that returns the new state, or you provide an object that the current state should be merged with as a first argument and a callback that will be executed after the state has been set as second argument.
Either this.setState(this.getInitialState) or this.setState(this.getInitialState()) or this.setState(newState, callback).
Check out the signature in the API here.