---
tags: REACT
---
# [筆記] React
- vue為雙向綁定資料與畫面,連動
- React單向,改資料更新畫面,更新畫面不會影響到資料
- `useState`, `useEffec` 最重要的兩個東東
## 參考
- [傳奇人物筆記Dan](https://overreacted.io/)
- [必看文章 A Complete Guide to useEffect](https://overreacted.io/a-complete-guide-to-useeffect/)
## JSX
- 經babel編譯
```htmlembedded=
<button type="button">Click Here!</button>
```
```javascript=
// function,props,children
React.createElement("button", {
type: "button",
}, "Click Here!");
```
```htmlembedded=
<div>
<button type="button">Click Here!</button>
</div>
```
```javascript=
React.createElement("div", null, React.createElement("button", {
type: "button"
}, "Click Here!"));
```
## PropTypes
`檢查參數型態`
```javascript=
import PropTypes from 'prop-types'
MyComponent.propTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool.isRequired,
optionalFunc: PropTypes.func,
// An object taking on a particular shape
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
}
```
# State操作
## 1. 新增 - 解構
```javascript=
setTodos([
{
id,
content: inputValue,
isDone: false,
},
...todos,
])
```
## 2. 刪除 - filter
```javascript=
const handleTodoDelete = id => {
setTodos(
todos.filter((todo) => todo.id !== id ),
)
}
```
## 3. 修改 - map
```javascript=
const handleToggleIsDone = id => {
setTodos(
todos.map((todo) => {
if(todo.id === id)
todo.isDone = !todo.isDone
return todo
}),
)
}
```
### a 的 href 防 javascript
```
<!-- 例 -->
javascript:alert(2)
```
# Hooks
[Hook flow圖](https://raw.githubusercontent.com/donavon/hook-flow/master/hook-flow.png)
[useHooks網站](https://usehooks.com/)
[從 Hooks 開始,讓你的網頁 React 起來](https://ithelp.ithome.com.tw/articles/10216355)
## 重要觀念
1. 只能在component第一層
2. 不能被function或 if-elase等包起來
## useEffect
- render完要做什麼事?(瀏覽器畫完畫面後想做什麼事)
- `array` 作為可選的第二個參數
```javascript=
import { useEffect } from 'react'
useEffect(()=>{
console.log('執行完畢')
})
// 僅在count更改時才重新執行 effect
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
```
- 傳空陣列,只有第**一次render會執行**
```javascript=
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(res=>{
console.log(res)
})
}, []);
```
- cleanup effect return 上個state值
```javascript=
useEffect(() => {
console.log('current ', value)
let i = value
if(i <= 10) {
i++
setValue(i)
console.log('setting ', i)
}
// cleanup function
return () => {
// 上一個value值
console.log('cleanup', value)
}
}, [value])
```
```javascript=
useEffect(() => {
WebSocket.CONNECTING(userID).subscribe(() => {
// ...
})
// cleanup function
return () => {
// 清掉上一個userID
WebSocket.disconnect(userID)
}
}, [userID])
```
## useLayoutEffect
- render完,瀏覽器 `paint` 前執行
# Hook Flow (Life Cycle)
[Hook flow圖](https://raw.githubusercontent.com/donavon/hook-flow/master/hook-flow.png)
## Mount
### lazy initialized
- 只執行一次
- useState給初始值(這邊只執行一次
## Update
- render
- update dom
- cleanup LayoutEffects
- Run LayoutEffects
- 瀏覽器paints畫面
- cleanup Effects
- Run Effects
## Unmount
- cleanup LayoutEffects
- cleanup Effects
# Memo: 避免不必要的re-render
```javascript=
import { memo } from 'react'
const Button = ({ onClick, children }) => {
console.log('rerender button')
return (
<button
onClick={onClick}
>
{children}
</button>
)
}
const MemoButton = memo(Button)
```
- input值變動時,MemoButton不會re-render
```jsx=
<input
type="text"
placeholder='enter something...'
value={value}
onChange={handleChange}
/>
<MemoButton
onClick={handleClick}
>
do button
</MemoButton>
```
## useCallback
- 以下範例,input 與 button無關時,input值有變動,button不要re-render
```jsx=
import useButton from '@/hooks/useButton'
const Button = ({ onClick, children }) => {
console.log('rerender button')
return (
<button
onClick={onClick}
>
{children}
</button>
)
}
const MemoButton = memo(Button)
function App() {
const { value, handleChange } = useInput()
const { textValue, handleClick } = useButton()
return (
<div className="App">
<input
type="text"
placeholder='enter something...'
value={value}
onChange={handleChange}
/>
<div>{value}</div>
<hr />
<MemoButton
onClick={handleClick}
>
do button
</MemoButton>
<div>Button text: {textValue}</div>
</div>
)
}
```
```jsx=
import { useState, useCallback } from 'react'
export default function useButton() {
const [textValue, setTextValue] = useState('')
const handleClick = useCallback(() => {
setTextValue('kerker' + textValue)
}, [textValue, setTextValue])
return {
textValue,
handleClick,
}
}
```
### 避免re-render: useMemo
```jsx=
const s = useMemo(() => {
return value ? greenStyle : redStyle
}, [value])
```