## React Beginner Guide: Learn the Must-Know Concepts with Examples

> *前情提要:通常在跟陌生人交流前,需要理解的基本React知識,這樣才不會一問三不知。以下會先以:props、state、context、refs 以及 lifecycle去做簡單介紹。
---
### Props (屬性)
> 從父元件中傳進子元件的資料,是唯讀的,不可在子元件中被更改。
```javascript=
//子元件
function Welcome(props) {
return <h1> Hello, {props.neme}!</h1>;
}
//父元件
function App(){
return <Welcome name="CHRIS" />;
}
```
### State (狀態)
> 元件內部可變的資料,用來控制UI變化。
```javascript=
import { useState } from 'react';
function Counter() {
//定義兩個參數
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times </p>
<button onClick={() => setCount(count +1)}>Click me</button>
</div>
)
}
```
### Context (上下文)
> 提供跨元件(不需層層傳 props)共享資料的方式,例如主題、語言、登入狀態等。通常跟props 用途區別為是否許多元件都需要使用到Value,以登入/登出為例:
```javascript=
import { creatContext, useContext, useState} from 'react';
//1.建立 Context
const AuthContext = creatContext();
//2.建立Provider物件
export function AuthProvider({children}) {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const login = () => setIsLoggedIn(true);
const logout = () => setIsLoggedIn(false);
return (
<AuthContext.Provider value={{ isLoggedIn, login, logout }}>
{children}
</AuthContext.Provider>
);
}
// 3. 建立自訂 Hook
export function useAuth() {
return useContext(AuthContext);
}
```
```javascript=
import { useAuth } from './AuthContext';
function LoginButton() {
const { login, isLoggedIn } = useAuth();
if (isLoggedIn) return null;
return <button onClick={login}>Log in</button>;
}
export default LoginButton;
```
```javascript=
import { useAuth } from './AuthContext';
function LogoutButton() {
const { logout, isLoggedIn } = useAuth();
if (!isLoggedIn) return null;
return <button onClick={logout}>Log out</button>;
}
export default LogoutButton;
```
```javascript=
import { useAuth } from './AuthContext';
function UserStatus() {
const { isLoggedIn } = useAuth();
return <p>{isLoggedIn ? 'You are logged in!' : 'You are not logged in.'}</p>;
}
export default UserStatus;
```
```javascript=
import { AuthProvider } from './AuthContext';
import LoginButton from './LoginButton';
import LogoutButton from './LogoutButton';
import UserStatus from './UserStatus';
function App() {
return (
<AuthProvider>
<h1>Welcome to My App</h1>
<UserStatus />
<LoginButton />
<LogoutButton />
</AuthProvider>
);
}
export default App;
```
可能會好奇為什麼能夠使用AuthContext.Provider的寫法,這攸關於Context底層:
> 1. Provider: // 用來「提供」值
> 2. Consumer: …, // 用來「接收」值(早期寫法)
createContext() 回傳的物件裡面就有這兩個屬性!可以直接寫 <AuthContext.Provider />
>Value: 是共享值,在這邊代表傳給AuthContext的共享值,透過useContext(AuthContext)可以存取Value裡面的值。

### Refs (參考)
> 直接取得 DOM 元素或元件實例的參考,常用來處理像是表單聚焦、動畫、播放控制、滾動捲軸到某處、讀取 DOM 的寬高位置、控制畫布(canvas)、SVG 或第三方元件等。
```javascript=
import { useRef } from 'react';
//點按鈕時,input 元素會被自動聚焦
function TextInputWithFocusButton() {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus(); // 直接操作 DOM
};
return (
<>
<input ref={inputRef} type="text" />
<button onClick={handleClick}>Focus the input</button>
</>
);
}
```

### Lifecycle (生命週期)
>指一個元件從被建立、更新、到被卸載(移除)的整個過程,就像是一個元件「出生 → 活著 → 死亡」的歷程。現階段基本上都是使用Hooks中useEffect去實現;不過也可以透過非Hooks的方式去實現,但只能使用Class Component的方式去實現。
以下透過兩種方式去呈現比較:
>1. 掛載(Mounting): 元件第一次出現在畫面上
>2. 更新(Updating): props 或 state 改變時
>3. 卸載(Unmounting): 元件從畫面移除時
分別對應:
>1. useEffect(() => {…}, [])
>2. useEffect(() => {…}, [依賴])
>3. useEffect 的 return function
1. Hooks:
```javascript=
import { useEffect } from 'react';
function MyComponent(props) {
useEffect(() => {
console.log('掛載:componentDidMount');
return () => {
console.log('卸載:componentWillUnmount');
};
}, []); // 空依賴陣列,只在掛載/卸載時執行
useEffect(() => {
console.log('更新:props 或 state 改變');
return () => {
console.log('清理上一次更新 effect');
};
}, [props.something]); // 有依賴才是更新
}
```
2. Class Component
```javascript=
class MyComponent extends React.Component {
componentDidMount() {
// 掛載:元件出現在畫面時執行
console.log('componentDidMount');
}
componentDidUpdate(prevProps, prevState) {
// 更新:元件 state 或 props 改變時執行
console.log('componentDidUpdate');
}
componentWillUnmount() {
// 卸載:元件從畫面上移除時執行
console.log('componentWillUnmount');
}
render() {
return <div>Hello Lifecycle!</div>;
}
}
```
場景應用:

---