狀態(state)使用方法 - useState()
- 導入
useState
函數。
- 調用
useState
函數,並傳入狀態初始值。
const [數據名, 修改相應數據狀態方法] = useState(初始值)
- 從
useState
函數返回值中,拿到狀態及修改狀態的方法。
- 在 JSX 中展示狀態。
- 調用修改狀態方法更新狀態。
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 29
|
import { useState } from 'react';
export default function APP() { const [count, setCount] = useState(0);
return ( <div> {/* 使用數據 */} {count}
{/* 修改數據 */} <button onClick={() => { setCount(count + 1); }} > 加1 </button> </div> ); }
|
注意事項: useState()
不能被嵌套在其他 if
/ for
/ 其他函數中。
錯誤 :no_entry_sign:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function APP() { let num = 1;
if(num == 2){ const [count, setCount] = useState(0); }
return ( <div> {count} <button onClick={() => { setCount(count + 1); }} > 加1 </button> </div> ); }
|
重點: React的狀態(state) 是不可直接更改的,必須透過相應的狀態修改方法 才能正確修改。
受控組件及非受控組件
受控組件
可以被 React 狀態(state) 控制的組件。
React 組件狀態是放在 state 中,而表單元素的 value 值也代表自己當前值。 React 通過將 state 與表單元素的 value 綁定再一起,在通過 state 來控制標單的值,從而保證單一數據元的特性。
非受控組件
通過手動操作 DOM 的方式來獲取表單的值(通過原生 DOM 來獲得),表單的值不受 React 的 state 控制。
在 React 中透過使用 Refs 就可以取得 DOM 節點。
React 組件間通信 - 通過參數(props)
目的: 每個組件都是獨立且封閉的,默認情況下**只能使用自己的數據(state)**,但在開發過程值中,組件不可避免的需要互相傳遞一些數據,讓各組件間進行互相溝通、數據傳遞就叫組件通信。
父傳子
父組件將要傳入的值,透過標籤的自定義屬性加入。
子組件通過參數 props 可獲得父組件傳入的值(會是一個 object)。
父組件 App
<自定義標籤 標籤自定義屬性名=傳入子組件值 />
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { useState } from 'react';
import Son from './Son';
export default function APP() { const [message, setMessage] = useState("我是父組件");
return ( <div> 我是父組件 我是父組件的 message: {message} <hr/> <div> 我是子組件 <Son text={message} /> // 傳到子組件中時,會以 {text: "message 值"} 呈現 </div> </div> ); }
|
子組件 Son
Function Component 中會有一個參數 props,通過該參數即可獲得從上層傳入的所有值,會以 object 呈現。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import { useState } from 'react'
export default function Son(props) { console.log(props);
const [message, setMessage] = useState("我是子組件 Son");
return ( <p> 我是子組件 Son 我接收了父(上)層傳來的 message: {props.text}。<br/> 我代表了自己本身的 message: {message}。 </p> ) }
|
子傳父
在父組件中定義一個 function,並將該 function 通過 props 的方式先傳入到子組件。在子組件調用該 function 時,就可以通過傳入子組件參數的方法來讓父組件獲得子組件的值。
父組件 App
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
| import { useState } from 'react'; import Son from './Son';
export default function APP() { const [message, setMessage] = useState("我是父組件"); const getChildValue = (childValue) => { console.log(childValue); setMessage(`我是父組件的 message, ${childValue}`) } return ( <div> 我是父組件 我是父組件的 message: {message}
<hr/> <div> 我是子組件 {/* props 可以接收方法 */} <Son getChildValue={getChildValue} /> </div> </div> ); }
|
子組件 Son
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { useState } from 'react'
export default function Son(props) { const [message, setMessage] = useState("我是子組件 Son"); const [text, setText] = useState("數據被修改了"); return ( <p> 我是子組件 Son 我代表了自己本身的 message: {message}。 <button onClick={() => { // 調用父組件傳入的方法 props.getChildValue(text); }} > 改變父組件中的 message </button> </p> ) }
|
兄弟間
兄弟間的通信非常麻煩,Son 組件必須先將值傳給父組件(App),再由父組件(App)通過 props 傳給 Daughter 組件。
父組件 App
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
| import { useState } from 'react'; import Son from './Son'; import Daughter from './Daughter';
export default function APP() {
const [message, setMessage] = useState("我是父組件");
const getChildValue = (childValue) => { console.log(childValue); setMessage(`我是父組件的 message,我要將 Son 組件的值 \"${childValue}\" 傳給 Daughter 組件`) }
return ( <div> 我是父組件 我是父組件的 message: {message}
<hr/> <div> 我是子組件群 <Son getChildValue={getChildValue} /> <Daughter message={message} /> </div> </div> ); }
|
子組件 Son
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { useState } from 'react'
export default function Son(props) { const [message, setMessage] = useState("我是子組件 Son "); return ( <p> 我是子組件 Son 我代表了自己本身的 message: {message}。
{/* 使用父組件傳來的方法,將子組件的值往上傳*/} <button onClick={() => { props.getChildValue(message); }} > 改變父組件中的 message </button> </p> ) }
|
子組件 Daughter
1 2 3 4 5 6 7 8 9
| export default function Daughter(props) { return ( <div> 我是子組件Daughter {/* 通過 props 接收父組件傳來的值 */} 我要接收 Son 組件訊息: {props.message} </div> ) }
|
多層嵌套的組件 - createContext 來實現跨組件通信
如果通信只有一層,使用上面的方法還不算麻煩,但是如果有多層的話,那簡直是惡夢。
如果是父組件要傳值給孫組件(2層),則可以通過 React 的 createContext 方法來解決通信問題。
每個組件都是一個檔案的情況下
- 創建一個新的檔案(Transmit.js)專門用來放置要傳遞的值的初始值,調用 createContext(defaultValue)。
1 2
| import { createContext } from 'react'; export const Transmit = createContext({});
|
- 引入 Transmit ,並使用 Transmit.Provider 包裹根組件,並提供數據。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { useState } from 'react'; import { Transmit } from './Transmit'; import Son from './Son'; export default function APP() { const [message, setMessage] = useState("我是父組件"); return ( <Transmit.Provider value={message}> {/* 根組件內容 */} <div> 我是父組件 我是父組件的 message: {message} <hr/> <div> 我是子組件 <Son /> </div> </div> </Transmit.Provider> ); }
|
- 需要用到數據的組件,使用 useContext(欲取得的數據的檔案) 來獲取數據。
1 2 3 4 5 6 7 8 9 10 11 12
| import {useContext} from 'react' import { Transmit } from './Transmit';
export default function GrandChild() { const msg = useContext(Transmit); return ( <div> GrandChild 組件: <span>{msg}</span> </div> ) }
|
可將 Transmit.js 是唯一個存放數據的空間,比較好理解。