---
# System prepended metadata

title: React
tags: [自學筆記]

---

# React

## props
```
'${}' //模板字符串

(prop)=>{
    document.title = `hello, ${props.name}` //name='abc'
}

console："hello, John"
```

```
{`${item?.title}`} //顯示指定字串或賦值

defaultValue={`${item?.title}`}
key={`Item${item?.id}`}
```

## JCX

### Function
* 箭頭函數
```
const FunctionName = () => {
    console.log(123);
};
```
* 匿名函數

![](https://hackmd.io/_uploads/rkB_h0VZp.png)

* UUID
```
crypto.randomUUID() //可以產生唯一的ID
```
```
let uuid = self.crypto.randomUUID();
console.log(uuid); 
```
![](https://hackmd.io/_uploads/HkjuGA4Za.png)

### disabled 寫法
```
//判斷式
const isButtonDisabled = newTitle === '' || newDept === '';

<Button 
   disabled={isButtonDisabled}>                
</Button>
```


## State

### import
```
import React, { useState } from 'react';
```

### 修改 state
:::info
state 的變數為 read-only，並不能用 this.state.變數=值直接修改state，而是必須要透過 React 預寫好的函式 setState() 來更改
:::

```
 changePercent(){
    this.setState({ percent:"70%" })
    //percent 是變數
  }
```

### 移除 state 
將 state 指定為 undefined
```
this.setState({mounted: undefined});
```

### 新增物件
![](https://hackmd.io/_uploads/BkEO8m6lp.png)

### 移除物件
![](https://hackmd.io/_uploads/ryFUeJBWa.png)

## use state
```
變數型態 [state變數名稱, setState函式名稱] = useState(state變數初始值)
```

![](https://hackmd.io/_uploads/Bku0IJHbT.png)

// 函式在語法上沒有限定命名原則，但一般會以set做為開頭

## useEffect

當 useState 或變數變動時，可以透過 useEffect 來監聽執行，而 useEffect 也是個通用的 Hook，如果找不到對應的 Hook 時也可以使用

```
useEffect(() => {
    console.log(123);
  })
```

* useEffect() 的第一個參數是函數，元件載入時會執行，每渲染一次，此函式就自動執行一次，在第一次載入頁面時，也會執行。

* useEffect() 的第二個參數，可以使用一個 Array 來指定 useEffect() 的資料，那只有資料發生變化時，就會從新渲染。

### useEffect() 常見用途

* 獲取資料/call API
* 事件的監聽或訂閱
* 改變 DOM 元素
* 輸出日誌

## useContext














:::info
一次做一件事，不要在useEffect()裡做多件事，例如 TodoList 有讀取、寫入、刪除，這三件事就需要寫成三個 useEffect()
:::

## Redux

1. ==state==：類似宣告變數，存放資料和狀態的地方。
2. ==reducer==：要修改 state 的話一定要透過 reducer。
3. ==action==：如要 reducer 有作用的話需傳入一個 action 去判斷要啟動哪個 reducer。
4. ==Provider==：在所有組件的最外面（通常是 Index.js）包一層Provider，傳入 store，被包覆的組件則可使用 store 的狀態。
5. ==store==：就是 state、reducer、action 的集合，換句話說，放 state、reducer、action 的那隻檔案就叫 store。 

### 流程
1. 創建 Store，用來放置集中處理的資料與方法的地方。
2. 在最外層使用 Privider 把整個 App 包起來，讓全部的組件皆可以使用 Store 內的資料與方法。
3. 撰寫 slice，存放 states (資料)和 reducers (方法)。
4. 在專案內讀取這些資料或更新這些資料。

### state
```
const initState = {
    name: 'Jack',
}
```

```
const reducer = (state = initState, action) => {
    switch (action.type){
        default:
            return state 
    }
}
```

每一個 Reducer 都會有兩個參數，第一個參數會將初始的資料狀態 initState 交由 Reducer 保管，第二個參數會傳入現在 reducer 要對 state 做什麼動作的指令及額外的參數。

> 以上程式碼沒有任何 action 指令描述的 Reducer，所以預設回傳了它所保管的 state ，在這裡就是上方的 initState。
> console.log() // {name: 'Jack'}

### store

Reducer 創建完成後，需要交由 store ，而 store 的工作就是在應用程式中負責整合所有的 Reducer。

首先在 redux 中 import 負責創建 store 的函式 createStore ，並將 Reducer 傳入以創建一個 store。

```
const store = configureStore({ reducer: allReducers });
```

:::info
注意！每個專案都只能有一個 store 存在
:::

### Provider

把 provider 包在最外面，讓整個專案都可以存取到
（放在index.js也可以，只要是最外層就好）

```javascript
import { Provider } from "react-redux";
import store from "@/store";

function App() {
  return (
    <Provider store={store}>
      //...
    </Provider>
  );
}

export default App;
```


### Slice

slice 是 toolkit的 概念，能將 Redux 原生的 state、reducer、action 都合在一包，稱為 slice。

1.  createSlice 是 toolkit 的工具，如沒有使用 toolkit，就需要自行創建 states、reducers、actions。
2. 從 toolkit 引入 createSlice，創建的時候需要的物件有：
    * ==initialState== : 狀態初始值，slice 只需要設定initialState，則不需設定 state。
    * ==reducers== : 可放許多函式，會有參數 state、action，state 用來修改狀態，可直接對 state 進行操作，action 則用來傳入參數。

```javascript
import { createSlice } from "@reduxjs/toolkit";
export const todoSlice = createSlice({
  name: "todo",
  initialState: {
    //...
  },
  reducers: {
    //...
  },
});
export default todoSlice.reducer;
```

補充：==push(action.payload)==，這是一個數組方法，用於將新的元素添加到 state.items 數組的末尾。在Redux中，通常是通過Action的payload來提供新的數據，以便更新應用程序的狀態。


## React Redux 函數

### **dispatch()**
將動作傳遞給 Redux store，以便觸發應用程式中的狀態更新

### **combineReducers()**
1. **將多個 reducer 組合成一個**： 在大型應用程式中，通常會有多個不同的 reducer，每個負責管理狀態的不同部分。combineReducers 允許你將這些 reducer 組合成一個根 reducer，它負責整合和分發動作，並處理整個應用程式的狀態。

2. **拆分狀態**： 通應用程式的狀態可以分為多個部分，每個部分對應一個 reducer。combineReducers 讓你在根 reducer 中指定每個部分的 reducer，並自動將它們的輸出整合為一個狀態對象。

```javascript
import { combineReducers } from 'redux';
import TodoListReduer from './TodoList';
import CounterReducer from './Counter';

const allReducer = combineReducers({
  counter: counterReducer,
  user: userReducer,
});

export default allReducer;

```

呼叫元件：
```
const 變數名稱 = useSelector(state => state.counter);
```

## RESTful API

* useEffect Hook： 
通常會使用 useEffect() 來發送 API 請求，頁面在渲染過後便會執行 useEffect() 中的指令。
```
useEffect(() => {
    // 在此獲取數據
}, []);
```

* useState Hook：
請求數據時，需要宣告狀態用來儲存往返的數據。
```
const [posts, setPosts] = useState([]);
```
 
React Rudex：呼叫 api 寫在 action.js 的 try() 裡面

### Fetch
* Fetch() 裡是強制參數，需填入路徑或 URL，返回後可使用 then() 和 catch() 的方式去處理成功和失敗。
```
import {useEffect} from "react";
const fetchData = () => {
return fetch("https://randomuser.me/api/")
 .then((response) => response.json())
 .then((data) => console.log(data));}
 
useEffect(() => {
 fetchData();
 }, []);

```

### Axios
```
import axios from “axios”
const fetchData = () => {
return axios.get(“https://randomuser.me/api/")
 .then((response) => console.log(response.data));}
```

### [範例參考](https://www.freecodecamp.org/chinese/news/how-to-consume-rest-apis-in-react/)



## Next.js

## onBlur