Spread operator [duplicate] - javascript

This question already has answers here:
How to return anonymous object from one liner arrow function in javascript? [duplicate]
(3 answers)
Closed 3 years ago.
I am having code from youtube tutorial, and i can not figure out why do we need parentheses(commented line), and if anyone can explain in simple way this code... thanks
const [{count, count2}, setCount] = useState({count: 10, count2: 20})
return (
<div className="App">
<button onClick={ () =>
setCount(
currentState => (//can not understand
{...currentState, count: currentState.count+1}
)
)}>+</button>
<h5>Count 1: {count}</h5>
<h5>Count2: {count2}</h5>
</div>
)

This has nothing to do with the spread operator.
The => of an arrow function can be followed by either:
An expression
A block
Since, in JavaScript, a { can start a block or an object initializer (which depends on context), anywhere you could put a block but want an object initializer you need to add wrap it in () so that the { is treated as the start of an expression.

why do we need parentheses
I guess because without them (), it won't work, throws the error even on compile time.
setCount(
currentState => (//can not understand
{...currentState, count: currentState.count+1}
)
)
setCount is a setState hooks. It has 2 syntax:
setCount( newStateOfCount ) (set state with direct value)
setCount( oldCount => newCount ) (set state using a callback)
And yours is the second one. With the callback return an object, you have 2 options:
currentState => {
return {
...currentState,
count: currentState.count+1
}
}
which is more verbose than
currentState => ({
...currentState,
count: currentState.count+1
})
So in the tutorial he used the second syntax, because it's more concise.
Without the parentheses it doesn't work:
currentState => {
...currentState,
count: currentState.count+1
}
Because the parser will understand that { is the begin of a function body, rather than an object, it won't be able to figure it out, without you explicitly give it the ()

Related

Typescript setInterval error: XYZ is already declared in the upper scope [duplicate]

This question already has answers here:
Using setInterval() in Typescript React
(3 answers)
Closed 1 year ago.
I am encountering a curious error where I create a handler function and attempt to set the current ref to the state's value plus 1:
const useTimer = () => {
const [seconds, setSeconds] = useState(0);
const counterRef = useRef(null);
const handleStart = () => {
counterRef.current = setInterval(() => {
setSeconds((**seconds**) => seconds + 1);
}, 1000);
};
return (
<button type="button" onClick={handleStart}>Start</button>
)
}
eslint is now kicking on that 'seconds' is already declared in the upper scope on line 8 column 10. and it's caused by the seconds parameter of setSeconds (highlighted with ** in the snippet above).
Question 1: Am I missing something programmatically or is this really just a false eslint error?
Question 2: When I remove null from useRef, counterRef.current is underlined with the error Type 'Timeout' is not assignable to type 'undefined'. How do I initialize useRef correctly when setInterval is going to be the future value?
EDIT: Found this answer in the react docs:
If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value.
Makes more sense why no-shadow kicked on. Thanks to all commenters.
Re. Question 1: this warning is valid. You are declaring two different variables named seconds in two different places, creating ambiguity in certain scopes.
const [seconds, setSeconds] = useState(0);
// ^^^^^^^
setSeconds((seconds) => seconds + 1);
// ^^^^^^^
I would fix this by renaming:
setSeconds((prevSeconds) => prevSeconds + 1);
Re. Question 2: type your ref as follows:
// If using NodeJS setInterval:
const counterRef = useRef<NodeJS.Timeout|null>(null);
// If using window.setInterval (ie. in a browser):
const counterRef = useRef<number|null>(null);
Edit: To support response to comment - setInterval and setTimeout return a number in a web browser.

Promise Arrangment and Syntax

I was wondering if anyone could clarify the following.
What is the difference between this:
function(arg).then((ret) => {
anotherFunc(ret);
}).catch(error)
and this:
function(arg).then((ret => {
anotherFunc(ret);
})).catch(error)
Difference is the brackets when the promise is returned.
Your second example looks strange. I think your question has to do more with arrow functions syntax. If arrow functions have one argument, you can skip the parentheses. For example .
const logA = a => console.log(a);
const logB = (b) => console.log(b);
As you see, logA argument doesn't have (), logB argument does have (b). They both work exactly the same way, just a syntax preference.
function(arg).then((ret) => {
anotherFunc(ret);
}).catch(error)
OR
function(arg).then(ret => {
anotherFunc(ret);
}).catch(error)
Are the same.

React useState hook does not seem to update the state on explicitly calling setter function

This is the code written
function App() {
const [number, setNumber] = useState(1);
const mapper = {
1: 'One',
2: 'two',
3: 'three'
}
const setFirst = () => {
setNumber(1);
console.log(number);
console.log(mapper[number]);
}
const setSecond = () => {
setNumber(2);
console.log(number);
console.log(mapper[number]);
}
const setThird = () => {
setNumber(3);
console.log(number);
console.log(mapper[number]);
}
return (
<div>
<button onClick={() => { setFirst(); }}>One</button>
<button onClick={() => { setSecond() }} >Two</button>
<button onClick={() => { setThird(); }} >Three</button>
</div>
);
}
Expected:
On click of setFirst(), number should be set to 1.
On click of setSecond(), number should be set to 2.
On click of setThird(), number should be set to 3.
What's happening is
On clicking in sequence
setFirst() -> setSecond() -> setThird()
in repeating fashion
Output:
1
One
1
One
2
Two
3
Three
1
One
Expected output:
1
One
2
Two
3
Three
1
One
2
Two
Can someone help me with this. I need help in figuring out where the bug is.
As Chris said in comment, setNumber is an asynchronous function, so its update is not visible right after it is performed.
Moreover, you should know that, at each render, each methods inside the component is "stacked" inside its current closure. Let me elaborate:
You render the component, which returns the button (assume just the first one). When the button is rendered, since setFirst it's linked to it, you can imagine a sort of room being created, in which all the external variables used inside setFirst are copied. Thus, since setFirst uses the variables number and mapper, a copy of them is created inside this "room";
When you finally click on setFirst, you run setNumber. This setNumber it does NOT update the number inside setFirst room, but it updates the number that will be used in the next render phase;
This example is to make you understand why, when you click on setSecond, you get logged 1 One: when the setSecond method was initialized for that render, number was still 1.
When setter function in eventloop. there is a asynchronous function. You can let be a sync function. but mostly we are not recommanded do this, so i prefer using callback to do this.
setNumber(2, () => {
console.log('');
})
Anti-Pattern The sync way
Promise.resolve().then(() => {
setNumber(2);
console.log(2);
})

Problems In JavaScript Arrow Function [duplicate]

This question already has answers here:
What do multiple arrow functions mean in JavaScript?
(7 answers)
When should I use a return statement in ES6 arrow functions
(6 answers)
Closed 3 years ago.
I'm a newbie
I've download some source in this link
https://github.com/the-road-to-learn-react/react-redux-example
i have some proplem
in file src/app.js line 4
const applyFilter = searchTerm => article =>
article.title.toLowerCase().includes(searchTerm.toLowerCase());
why this can't work with
const applyFilter = searchTerm => article =>{
article.title.toLowerCase().includes(searchTerm.toLowerCase());
}
or
const applyFilter = searchTerm => {article =>
article.title.toLowerCase().includes(searchTerm.toLowerCase());
}
and in line 14 when call the funtion
articles.filter(applyFilter(searchTerm))
const applyFilter = searchTerm => article =>
article.title.toLowerCase().includes(searchTerm.toLowerCase());
this in my mind is call an arrow function inside an arrow function?
How can they put var 'article' in??
Arrow function syntax is kinda like this
(a) => b(a);
is equivalent to
function(a) {
return b(a);
}
However, when you add {} to an arrow function, it changes the meaning:
(a) => { b(a); }
is equivalent to
function(a) {
b(a);
// notice that this doesn't actually return anything,
// it just calls a function and does nothing with the result
}
So you have to add a return statement when you add brackets
(a) => { return b(a); }

Javascript ES6 Difference between ()=>() and ()=>{} [duplicate]

This question already has answers here:
Arrow function without curly braces
(9 answers)
Closed 6 years ago.
I have seen a code something like while learning React
const LinkCell = ({rowIndex, data, col, ...props}) => (
<Cell {...props}>
{data.getObjectAt(rowIndex)[col]}
</Cell>
);
Also, so far I thought that in ES6 function shorthand is
let sum = (a, b)=>{
return a + b;
}
How the first one is different from the second one ?
() => () is a one liner shorthand of () => { doSomething() OR return; }.
Anyways, if you need more manipulations and need more than one line statement, you should go for () => {} syntax otherwise you can use a shorthand syntax () => ()
The following are also treated as one line statement. But to use with () => () syntax, you need to rewrite it without return statement,
// The below one line statement can be rewritten as below
if (true ) return something;
// rewritten of above one
() => ( a > b ? a : b)
// one line statement
if (true ) invoke(); // This will go like, () => (a ? a.invoke() : b.invoke())
// one line statement
for(var i in results) doSomething();
//And your jsx statement which can be tread as one liner
<Cell {...props}>
{data.getObjectAt(rowIndex)[col]}
</Cell>
with the ()=> () syntax imagine if there was an implicit return statment e.g. () => {return ()}

Categories

Resources