0%

React Hook — React的狀態管理(一) UseState、createContext

React Hook — React 的狀態管理(一) UseState、createContext

🔖 什麼是 useState ?

React 的 useState 可以讓我們「手動管理狀態」,也就是說當我們改變了一個元件的資料狀態,例如文字、顏色等等,我們可以不用再刷新頁面,而是在頁面直接渲染。
而 React 的特色就是資料的「單向流綁定」,當某資料狀態改變了,可以讓整個畫面相同資料的狀態改變。

UseState 用法

這裡假設目前的程式環境已支援 React

從 React 引入 useState

1
import React, { useState } from 'react';

現在,我們可以利用 useState 這個方法

useState 語法

1
const [state, setState] = useState();
  • 在我們使用 useState 宣告 state 變數,他會回傳一個含有兩個值的 array

    • 第一個值是 state : 目前狀態的設定值
    • 第一個值是 setState : 可以更新狀態的 function
  • useState() 的括號 ( ) 內為初始設定的值

  • useState 語法總結:

    • useState 使用 JS 的解構賦值語法宣告了兩個變數 statesetState,而這兩個變數名稱是其實可以隨意設定的唷!
    • 而上段語法可以看成:
    1
    2
    3
    const stateVariable = useState(); // 回傳兩個值的 array
    const state = stateVariable[0]; // 第一個值
    const setState = stateVariable[1]; // 第二個值
  • setState 函式的參數重點:

    • Pass the state, Run Everytime. eg. setCount(count + 1)
    • Pass the function, Run only the very first time when your component render. eg. setCount(prev => prev + 1)

實作範例

這邊以一個點擊按鈕後改變 input 的值做示範。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function App() {
const [value, setValue] = useState('Hello World')

return (
<div className="App">
<header className="App-header">
<p>
<input type="text" value={value} />
<button onClick={() => {
value === 'Hey~~~'
? setValue('Hello World')
: setValue('Hey~~~')
}}>{btnText}</button>
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}

export default App;

這是點擊 buttoninput 值的初始狀態

react

這是點擊 buttoninput 值的狀態

react

🔖 全域狀態管理(Context API) — createContext

當我們希望可以將一個狀態在其他地方使用,但又不想一個一個透過 Props 傳入時,就可以透過 Context API 來讓資料狀態在全域的情況下都可以使用!

createContext 用法

✏️ 主要有三個步驟:

  1. Create
    創建一個 Context 物件 (Context object) ➡️ createContext
  2. Provide
    在 component 中提供指定的 Context 物件
  3. Use
    在需要資料的 component 裡使用創建的 Context 物件 ➡️ useContext

接下來會以 Todolist 的例子來說明 createContext 的用法

Step1. Create the context

create-react-app 專案資料夾裡的 src 資料夾內,建立一個命名為 Contexts.js 的檔案。

Contexts.js 檔案中,我們會從 React 載入 createContext,再利用 createContext() 創建 context 物件,並命名這個 context 物件為 TodosContext,然後再 export 這個 context 物件。

1
2
3
4
5
// Contexts.js

import { createContext } from 'react';

export const TodosContext = createContext()

Step2. Provide the context

TodosContext 載入到要提供資料狀態出去的地方。

1
2
3
// TodoApp.js

import { TodosContext } from './Contexts.js';

利用 <TodosContext.Provider></TodosContext.Provider> 將要提供的區域包圍起來

並且將預設資料狀態值 todos 放到屬性 value 裡,context 物件 TodosContext 會接收這個資料狀態並提供給需要的 component,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// TodoApp.js

function TodoApp() {
// 要提供的資料狀態
const [todos, setTodos] = useState([
{ id: 1, title: 'Have a dinner', completed: true },
{ id: 2, title: 'running', completed: false }
])

return (
<TodosContext.Provider value={{todos}}> // 這裡傳進去的物件為 {todos: todos},因為命名相同而縮寫
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<TodoList />
</header>
</div>
</TodosContext.Provider>
);
}

export default TodoApp;

最後,記得再 export 這個 component。

Step3. Use the context

在要使用的檔案裡面,一樣先載入 context 物件 TodosContext

1
2
3
4
// TodoList.js

import { TodosContext } from './Contexts.js';
import { useContext } from 'react';

然後在要使用這個 context 物件的 component 裡面,我們會利用 useContext() 去使用 TodosContext提供的資料狀態。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// TodoList.js

const TodoList = () => {
const {todos} = useContext(TodosContext)

return (
<div className="App">
<header className="App-header">
<h1>My Todo List</h1>
<ul>
{
todos.map((todo, index) => {
return <ListItem key={todo.id} index={index} title={todo.title} todo={todo} todos={todos} completed={todo.completed} />
})
}
</ul>
</header>
</div>
);
}

export default TodoList;

結論就是,我們若想使用全域狀態的方法,其實只要知道創建(Create) → 提供(Provide) → 使用(Use) 三個步驟即可在任何地方使用所有資料!

下方會提供上面的程式碼,有多加一項功能但不影響閱讀,若有需要可以參考唷!

🔎 參考資料