# 1222 React ## 範例01 ``` <html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <!-- 以下載入react 17.0.1--> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.development.min.js"></script> <!-- 以上載入react --> <!-- 以下載入babel.js JSX即時轉譯器 效能不好--> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.js"></script> <!-- 以上載入babel.js--> </head> <body> <div id="app"></div> <script type="text/babel" src="app.js"></script> <!-- type="text/babel" 會將app.js用babel做編譯--> </body> </html> ``` 要使用React要在html引入 ``` <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.development.min.js"></script> ``` 以及轉譯器 `<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.js"></script>` 會轉譯React中的JSX語法 `<script type="text/babel" src="app.js"></script>` 加上babel標籤會將src="app.js"以babel做編譯 --- ``` ReactDOM.render( <div> <h1>Hello, world!!</h1> <h2>Hello, react!!</h2> </div>, document.getElementById('app') ) ``` ### JSX語法 不是原生JS ReactDOM.render(JSX元素,html動元素) JSX元素只能有一個元素,所以要放多個元素要用div包成一個元素 --- ## 範例02:Component ``` function FunctionalComponent(){ return( <div className="functional-component"> 這是functionalComponent組件 <br/> 今天日期: { new Date().toDateString() } </div> ) } ReactDOM.render( <div> <div/> //在JSX中可以自己結束自己 <FunctionalComponent/> <FunctionalComponent/> <FunctionalComponent/> <FunctionalComponent/> </div> , document.getElementById('app') ) ``` * `React.Component`已經是舊寫法少用,新專案不用 * 只要是React的Component的function名稱嚴格規定要用大寫開頭"F"unctionalComponent,用小寫會出錯會被判斷為html標籤 * JSX元素支援JavaScript寫法,所以元素中出現`Date().toDateString()`有括弧的寫法,都會進行JS運算 * `<div className="functional-component">`要用classNameb如果用class雖然會動但在開發者工具會報錯 --- ## 範例03:props ``` function FunctionalCard(props){ return ( <div className="card"> <img className="img" src={props.img} /> <div className="name">{props.name}</div> <div className="quote">{props.children}</div> </div> ); } ``` * props是function的參數,只會有一個,雖然不是專有名詞但是統一用props * children是特殊內建專用字不可亂改,會將FunctionalCard其他未指定名稱的參數放入 --- ``` ReactDOM.render( <div> <FunctionalCard img="http://fakeimg.pl/200x80/?text=milkmidi" name="Component" /> <FunctionalCard img="http://fakeimg.pl/200x80/ff0000/?text=pipi" name="Component"> <h1>這裡可以放 children </h1> </FunctionalCard> </div> ); ``` ``` <FunctionalCard img="http://fakeimg.pl/200x80/?text=milkmidi" name="Component" /> ``` * 寫法像html的屬性,這裡的img,name都是自定義的名稱,會代入到FunctionalCard的props * --- ## 範例4:State ``` function Counter() { var [count, setCount] = React.useState(0); return ( <div className="counter"> <h1>Counter</h1> <div className="count">{count}</div> </div> ); } ReactDOM.render( <div> <Counter/> </div> , document.getElementById('app') ); ``` * State是Component自身的變數,可以有多個State * `var [count, setCount]`一般寫法[name,setName]要寫成一組(不成文規定),setCount是修改數值用,不能直接改count * `function Counter(props) { var [count, setCount] = React.useState(0); ......` 意思為Counter這個function有一個變數count其初始值為0 如果要render多個Counter並帶不同初始值可以改寫成 ``` function Counter(props) { var [count, setCount] = React.useState(props.count); return ( <div className="counter"> <h1>Counter</h1> <div className="count">{count}</div> </div> ); } ReactDOM.render( <div> <Counter count={0} /> <Counter count={1} /> </div> , document.getElementById('app') ); ``` ## 查如果props未定義時,如何設定初始值 --- `var [count, setCount] = React.useState(props.count);` 這是ES6結構函式新語法,等於下面三行程式碼 ``` const arr = React.useState(props.count) const count = arr[0] const setCount = arr[1] ``` --- ### 加1計數 ``` function Counter(props) { //* // TODO var [count, setCount] = React.useState(props.count); const atClick =() => { setCount(count + 1) } return ( <div className="counter"> <h1>Counter</h1> <div className="count">{count}</div> <button onClick={atClick}>+1</button> </div> ); // */ } ReactDOM.render( <div> <Counter count={1} /> <Counter count={1} /> </div> , document.getElementById('app') ); ``` 在JSX註冊事件: `<button onClick={atClick}>+1</button>` 在標籤後寫上on事件={at事件},at事件是習慣寫法 在定義at事件行為 ``` const at事件 =() => { 行為 } ``` --- ## 例題5 ``` function UserGreeting(props){ return <h1 className="user">{props.name}登入成功</h1> } function GuestGreeting() { return <h1 className="guest">Please sign up.</h1>; } function App(){ //* // TODO const [isLoggedIn, setLoggedIn] = React.useState(false); const atClick = () => { setLoggedIn(!isLoggedIn); } return ( <div className="app"> <button onClick={atClick}>{isLoggedIn ? '登出' : '登入'}</button> {isLoggedIn ? <UserGreeting /> : <GuestGreeting />} {isLoggedIn && <UserGreeting name="milkmidi" />} </div> ) // */ } ReactDOM.render( <App />, document.getElementById('app') ); ``` * ` const [isLoggedIn, setLoggedIn] = React.useState(false);`這裏isLoggedIn型別為布林,會跟帶入的值(false)型別相同 * && 用法為當左邊成立時,會render右邊 --- ## 範例7:生命週期lifecycle 1446 ``` function Clock() { React.useEffect(() => { console.log('componentDidMount') return () => { console.log('componentWillUnmount'); } }, []); return ( <div className="my-component"> <h2>react useEffect</h2> </div> ) } ``` * 跟生命週期有關的使用useEffect * `console.log('componentDidMount')`時component誕生 * `return () => { console.log('componentWillUnmount');}` 時component死亡 * 目前Clock的第二個參數放[],放[]有其他用途 --- ## 範例8 ``` const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map((number) => number * 2); function List(){ //* // TODO const [list, setList] = React.useState(['學會 JS', '學會 React', '年薪百萬']); const atAddClick = () => { var newList = list.concat(new Date().toString()); setList(newList); } return ( <div> <button onClick={atAddClick}>Add</button> <ol className="list"> { list.map(function (text) { return <li key={text}>{text}</li>; }) } </ol> </div> ) // */ } ReactDOM.render( <List />, document.getElementById('app') ); ``` * key是react規定使用(進階) 1318