iT邦幫忙

0

Day58 (React)

1.useContext 之演進

可接元件並分享資料
只有function元件可使用,class元件不能使用

(1)function階層繼承 缺點:中間改變就斷掉了
(Lab_useContext > index_0.html)

      function Me(props) {
        return <h3>{props.secret}</h3>; // 3.在使用Father的方法取得資料
      }

      function Father(props) {
        return <Me secret={props.secret} />; // 2.把GrandFather的secret給Me  //4.回傳給GrandFather
        // return (
        //   <h3>{props.secret}</h3>
        // )
      }

      function GrandFather(props) {
        let [secret, setSecret] = React.useState("work harder or work smarter"); // 1.secret設定為字串 setSecret=方法  //5.變更後顯示
        return (
          <React.Fragment>
            <Father secret={secret} />
          </React.Fragment>
        );
      }

(2)雖然Father不用收,但還是很麻煩==
(Lab_useContext > index_1.html)

      function Me(props) {
        // 3.Provider搭配Consumer並使用=>接資料
        return (
          <heirloom.Consumer>
            {
              secret =>
                <h3>{secret}</h3>
            }
            
          </heirloom.Consumer>
        );
      }

      function Father(props) {
        return <Me />             // 2.回傳Me,不用接GrandFather
        // return (
        //   <h3>{props.secret}</h3>
        // )
      }

      function GrandFather(props) {
        let [secret, setSecret] = React.useState("work harder or work smarter");
        return (
          // 1.GrandFather把傳家寶跟<Father />綁在一起,所以Father不用接
          <React.Fragment>
          <heirloom.Provider value={secret}>  
            <Father />
          </heirloom.Provider>
          </React.Fragment>
        );
      }

(3)使用 useContext取得資料,createContext限制只有哪些元件可取得
(Lab_useContext > index_2.html)

      // useContext取得資料,createContext限制只有哪些元件可取得
      // 1. React.createContext()只有在這個範圍內的元件,才能使用
      var heirloom = React.createContext();

      function Me(props) {
        let secret = React.useContext(heirloom); // 4.useContext可以取得資料
        return <h3>{secret}</h3>;
      }

      function Father(props) {
        // 3.Father包含<Me />
        return <Me />;
        // return (
        //   <h3>{props.secret}</h3>
        // )
      }

      function GrandFather(props) {

        //回傳陣列 ; useState設定secret=字串,setSecret=ƒ()
        let [secret, setSecret] = React.useState("work harder or work smarter"); 

        let heirloomState = { secret, setSecret };
        console.log(heirloomState);
        return (
          // 2.設定範圍 GrandFather包含<Father />
          <React.Fragment>
            <heirloom.Provider value={secret}>
              <Father />
            </heirloom.Provider>
          </React.Fragment>
        );
      }

(4)最終版本:設定好可以使用的元件範圍,及可以使用的物件

      // 1. React.createContext()只有在這個範圍內的元件,才能使用
      var heirloom = React.createContext();

      // 3.使用useContext就可取出傳家寶,取得secret, setSecret
      function Me(props) {
        let { secret, setSecret } = React.useContext(heirloom);
        // 4.事件處理程序 拿secret, setSecret來用
        let doTest = () => {
          setSecret("Work smarter"); //把setSecret方法的倉庫拿來,使用
          document.title = Date();
        };
        // 4.事件處理程序 拿secret, setSecret來用
        return (
          //把secret字串的倉庫拿來,使用
          <div>
            <h3>{secret}</h3>
            <button onClick={doTest}>test</button>
          </div>
        );
      }

      function Father(props) {
        // 3. Father包含<Me />
        return <Me />;
        // return (
        //   <h3>{props.secret}</h3>
        // )
      }

      function GrandFather(props) {
        // 回傳陣列 ; useState設定secret=字串,setSecret=ƒ()改變資料的方法
        let [secret, setSecret] = React.useState("work harder or work smarter");
        // heirloomState 建立成一個物件,讓Provider(傳家寶)的值={}
        let heirloomState = { secret, setSecret };

        return (
          // 2. 設定範圍 GrandFather包含<Father /> 並設定傳家寶Provider
          // heirloomState = { secret, setSecret }; 物件
          <React.Fragment>
            <heirloom.Provider value={heirloomState}>
              <Father />
            </heirloom.Provider>
          </React.Fragment>
        );
      }

2.物件{}收物件{},[]收[]

        //useState回傳[],[]收下
        let [secret, setSecret] = React.useState("work harder or work smarter");

        //heirloomState是物件{} 
        let heirloomState = { secret, setSecret }; 

          <React.Fragment>
            <heirloom.Provider value={heirloomState}>  //{}收下
              <Father />
            </heirloom.Provider>
          </React.Fragment>

3.useMemo 改變該變數才跑此程式,為了節省效能,useMemo會記住該變數的原始值

(Lab_useMemo > index_OK.html)

      // 3.跑程式
      function App(props) {

        var [data1, setData1] = React.useState(1); //useState回傳[],只能用[]裝
        var [data2, setData2] = React.useState(1);

        var workResult = React.useMemo(() => {
          //useMemo會記憶原本data1是甚麼
          //此處只用data1
          return longTimeWork(data1); //參數
        }, [data1]); //資料 ; 4.判斷:當[data1]改變我才跑這個 return longTimeWork(data1) function,如果[data1]沒有改變就不會跑

        let changeData1 = () => {
          // 1.按按鈕 data1 +1
          setData1(data1 + 1);
        };

        //按第二個按鈕不會執行workResult 節省效能
        let changeData2 = () => {
          setData2(data2 + 1);
        }; C:\temp

        // 2.執行return
        return (
          <React.Fragment>
            <h3>
              workResult: {workResult}, data1: {data1}, data2: {data2}
            </h3>
            <button class="btn btn-outline-success" onClick={changeData1}>
              change data1
            </button>
            <button class="btn btn-outline-primary" onClick={changeData2}>
              change data2
            </button>
          </React.Fragment>
        );

4.介紹React + Node.js整體重跑一遍

(1)
Simple React Snippets 套件安裝 => 元件產生器
Snippets 簡寫
https://marketplace.visualstudio.com/items?itemName=burkeholland.simple-react-snippets

(2)Lab_counters > counter-app

create-react-app counter-app
建立資料夾counter-app

npm install bootstrap@4.1.1
counter-app資料夾內安裝bootstrap@4.1.1

npm start
跑package.json "start": "react-scripts start",
http://localhost:3000/

(3)Lab_counters > src > index.js

import App from './App'; //引用有物件的.js 需from
import 'bootstrap/dist/css/bootstrap.min.css'; //引用單純沒有物件的.js或.css 無須from

(4)Lab_counters > src > components > counter.jsx
imrc 快速建立引用
cc 快速建立類別
按tab跳行

     import React, { Component } from 'react';
     class Counter extends Component {
         state = {  }
         render() { 
             return ( <h1>hello</h1> );
         }
     }
 
     export default Counter;

(5)Lab_counters > src > index.js
改引用components/counter.jsx

import Counter from './components/counter.jsx';

     ReactDOM.render(
       // 測試看看有沒有引用到BS
       <React.StrictMode>
         <Counter />
         <button className="btn btn-outline-success">OK</button>
       </React.StrictMode>,
       document.getElementById('root')
     );

此時會顯示hello http://localhost:3000/

(6)Lab_counters > src > components > counter.jsx
使用方法formatCount()

    formatCount(){
        // 方法1.
        // return this.state.count === 0? "Zero" : this.state.count ; 
        // 方法2. this.state做成物件
        var {count} = this.state;
        return count === 0? "Zero" : count ;
    }
    render() { 
        return ( 
        <div>
            <span>{this.formatCount()}</span><hr />
            <button className="btn btn-outline-success">增加</button>
        </div> 
        );
    }

(7)增加圖片、樣式

    state = {  
        count:0,
        imgUrl: "https://dummyimage.com/200x200/000/fff"
    }

    //製作樣式物件 大寫必要font"W"eight(CSS內樣式)
    styles = {
        fontWeight:"bold",
        fontSize:"3em",
        fontStyle:"italic"
    };

    render() { 
        return ( 
        <div> 
            //圖片
            <img src= {this.state.imgUrl} /><hr />
            //新增樣式
            <span style={this.styles} className="badge badge-primary m-2">{this.formatCount()}</span><hr /> 
        </div> 
        );
    }

(8)製作判別式 並 設定套用不同樣式

    styles = {
        fontWeight:"bold",
        fontSize:"3em",
        fontStyle:"italic"
    };

    formatCount(){
        // 方法1.
        // return this.state.count === 0? "Zero" : this.state.count ; 
        // 方法2. this.state做成物件
        var {count} = this.state;
        return count === 0? "Zero" : count ;
    }

    //數值0=會變成黃色
    getBadgeClasses() {
        let myClassName = "badge m-2 ";
        myClassName += (this.state.count === 0) ? "badge-warning" : "badge-primary";
        return myClassName;
    }

    render() { 
        return ( 
        <div>
           

            {/* 設定藍色 */}
            <span style={this.styles} className="badge badge-primary m-2">{this.formatCount()}</span><hr />

            {/* render內,設定紅色 */}
            <span style={this.styles} className={myClassName}>{this.formatCount()}</span><hr />

            {/* getBadgeClasses(),設定黃色 */}
            {/* styles +  getBadgeClasses + formatCount 樣式在遇到0的時候會變成黃色 */}
            <span style={this.styles} className={this.getBadgeClasses()}>{this.formatCount()}</span><hr />

        </div> 
        );
    }

(9)製作tage項目[]

    class Counter extends Component {
    state = {  
        imgUrl: "https://dummyimage.com/200x200/000/fff",  //製作圖片物件
        count:0,
        tage : ["tage1","tage2","tage3"]
    }

    render() { 
        return ( 
            <ul>
                {/* tage有幾個就跑幾個 */}
                {/* index.js:1 Warning: Each child in a list should have a unique "key" prop. */}
                {/* 警告:要給tage唯一的key 所以幫li增加key */}
                {this.state.tage.map(x=> <li key={x}>000</li>)}
                {this.state.tage.map(x=> <li key={x}>{x}</li>)}
            </ul>
        </div> 
        );
    }

(10)把tage項目製作成function方法顯示

    class Counter extends Component {
    state = {  
        imgUrl: "https://dummyimage.com/200x200/000/fff",  //製作圖片物件
        count:0,
        tage : ["tage1","tage2","tage3"]
    }


    renderTags(){
        if(this.state.tage.length > 0 ){
            return <h3>我有東西唷!!請嘗試改變我~</h3>
        }
        return(
            <ul>
                {this.state.tage.map(x=> <li key={x}>{x}</li>)}
            </ul>
        );
    }


        render() { 
          return ( 
           <div>
             <ul>
                {/* &&判斷方式,前面true才會判斷後面,並顯示後面 */}
                {/* 實驗:把tage : ["tage1","tage2","tage3"]清空 */}
                {this.state.tage.length == 0 && "請建立一個清單"} <br />
                {this.renderTags()}
             </ul>
           </div> 
          );
        }


5.方便小工具,剪貼簿WatchClipboard.exe

複製過的東西會貼在上面
截圖會被放到 C:\temp

https://ithelp.ithome.com.tw/upload/images/20210830/20137684SlKIFo9VTG.png


6.能否使用JQ在react?

可以,npm i jquery 要安裝

import 'jquery/dist/jquery';

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言