# Hook
---
What is Hook?
---
Hooks are a fundamentally simpler way to encapsulate ==stateful== behavior and ==side effects== in user interfaces
---
```javascript=1
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
```
---
Deep dive: How do React hooks really work?
---
build a Hooks clone in just ==29 lines== of readable JS
---
It might just help your JS fundamentals if you go through this exercise. Don’t worry, ==it’s not that hard!==
---
What is Closures?
---
MDN:
A closure is the combination of a ==function== bundled together (enclosed) with references to its ==surrounding state== (the lexical environment)
---
The scope
```javascript=1
function foo() {
let count = 0;
console.log(count);
}
foo(); // 0
console.log(count); // ReferenceError: count is not defined
```
---
Scopes nesting
```javascript=1
function init() {
var name = 'apa yu'; // local variable
function displayName() { // displayName() is the inner function, a closure
alert(name); // use variable declared in the parent function
}
displayName();
}
init();
```
---
內層區塊可以存取定義在外層區塊的變數。反過來說,外層區塊沒辦法存取內層區塊的變數。
~~你的就是我的,我的還是我的~~
---
函式可以當成回傳值回傳
---
```javascript=1
function init() {
var name = 'apa yu'; // local variable
function displayName() { // displayName() is the inner function, a closure
alert(name); // use variable declared in the parent function
}
return displayName;
}
const sayHi = init();
sayHi();
```
---
Closure 可以「保留」環境
---
so what?
---
```javascript=1
function makeAdder(x) {
function add(y) { // closure
return x + y;
}
return add; // return function
}
const add5 = makeAdder(5); // keep variable
const add10 = makeAdder(10); // keep variable
add5(2) // 7
add10(2) // 12
```
---
```javascript=1
function useState(initialValue) {
var _val = initialValue; // local variable
function state() { // closure
return _val;
}
function setState(newVal) { // closure
_val = newVal;
}
return [state, setState]; // return function
}
var [count, setCount] = useState(0); // keep variable
console.log(count()); //0
setCount(1);
console.log(count()); //1
```
---
~~fucntion~~
variable
---
```javascript=1
function useState(initialValue) {
var _val = initialValue; // local variable
// function state() { // closure
// return _val;
// }
function setState(newVal) { // closure
_val = newVal;
}
return [_val, setState]; // return variable and function
}
var [count, setCount] = useState(0);
console.log(count); //0
setCount(1);
console.log(count); //0 ??????????
```
---
stale closure
```javascript=1
function createIncrement(i) {
let value = 0;
function increment() {
value += i;
console.log(value);
const message = `Current value is ${value}`;
return function logValue() {
console.log(message);
};
}
return increment;
}
const inc = createIncrement(1);
const log = inc(); // logs 1
inc(); // logs 2
inc(); // logs 3
// Does not work!
log(); // logs "Current value is 1"
```
---
解決方式A. Use a fresh closure
```javascript=1
const inc = createIncrement(1);
inc(); // logs 1
inc(); // logs 2
const latestLog = inc(); // logs 3
// Works!
latestLog(); // logs "Current value is 3"
```
---
解決方式B. Close over the changed variable
```javascript=1
function createIncrementFixed(i) {
let value = 0;
function increment() {
value += i;
console.log(value);
// const message = `Current value is ${value}`;
return function logValue() {
const message = `Current value is ${value}`;
console.log(message);
};
}
return increment;
}
const inc = createIncrementFixed(1);
const log = inc(); // logs 1
inc(); // logs 2
inc(); // logs 3
// Works!
log(); // logs "Current value is 3"
```
---
```javascript=1
const MyReact = (function() {
let _val // hold our state in module scope
return {
render(Component) {
const Comp = Component()
Comp.render()
return Comp
},
useState(initialValue) {
_val = _val || initialValue // assign anew every run
function setState(newVal) {
_val = newVal
}
return [_val, setState]
}
}
})()
```
---
```javascript=1
function Counter() {
const [count, setCount] = MyReact.useState(0)
return {
click: () => setCount(count + 1),
render: () => console.log('render:', { count })
}
}
let App
App = MyReact.render(Counter) // render: { count: 0 }
App.click()
App = MyReact.render(Counter) // render: { count: 1 }
```
---
Deep dive: How do React hooks really work?
https://www.netlify.com/blog/2019/03/11/deep-dive-how-do-react-hooks-really-work/
Be Aware of Stale Closures when Using React Hooks
https://dmitripavlutin.com/react-hooks-stale-closures/
A Simple Explanation of JavaScript Closures
https://dmitripavlutin.com/simple-explanation-of-javascript-closures/
{"metaMigratedAt":"2023-06-15T11:06:02.703Z","metaMigratedFrom":"Content","title":"Hook","breaks":true,"contributors":"[{\"id\":\"a1061309-7a7f-42b9-b144-e7e479bb7747\",\"add\":5938,\"del\":731}]"}