## React Beginner Guide: Learn the Must-Know Concepts with Examples ![1babba304aeae6d32624208602745fd2](https://hackmd.io/_uploads/S1GT9rT0Je.jpg) > *前情提要:通常在跟陌生人交流前,需要理解的基本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裡面的值。 ![image](https://hackmd.io/_uploads/SyRkpBTCkx.png) ### 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> </> ); } ``` ![image](https://hackmd.io/_uploads/B1HfTrp01g.png) ### 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>; } } ``` 場景應用: ![image](https://hackmd.io/_uploads/SkF96raCyx.png) ---