0%

想在 Opera 瀏覽器上使用 react 延伸套件,卻發現找不到?

沒關係

我們都知道 google 的擴充套件很豐富,所以 opera 提供了一個套件叫做 install Chrome extension
(該不會就是因為有這個 opera 的套件才會那麼不足XD)

首先到 opera 的套件庫 搜尋 install Chrome extension

或是直接到這個網頁

接著就可以來到 Chrome 線上應用程式商店下載你要的套件啦

由於裝的不是 opera 官方提供的套件,下載後可能會需要自己手動啟用他喔

前言

在使用物件導向程式設計時,一定會碰到this(在python裡是self)

要百分之百了解this的作用原理其實談不上容易,但簡單來說:

在一個 class 中呼叫this時,this指的是那個 class 本身

或是更 general 一點:

誰呼叫到thisthis就是誰

但最近遇到一個情形,呼叫this的時候找不到理應存在的變數

情形

這是一個 IconDisplayer 物件
調用 display() method,回傳 <Image>

1
2
3
4
5
6
7
8
const IconDisplayer = {
Current: {
USD: <Image source={require('./src/image/nations/united-states.png')} />
},
display: () => {
if (currency === 'USD') { return (this.Current.USD) }
}
}

運行時他會告訴你:

TypeError: Cannot read property ‘Current’ of undefined

意思就是說,程式找不到 Current 這個變數
但是很奇怪,明明就定義在物件裡R,也用了this
應該找得到才對呀


原因

後來查了一下發現一切都是 arrow function 的緣故

  • MDN & W3Schools:

    • In arrow functions, this retains the value of
      the enclosing lexical context’s this.
    • Arrow functions do not have their own this.
    • In global code, it will be set to the global object.

如果是呼叫以前的傳統函數,每次都會建立一個環境 (Function Execution Context)來運行,並把當時的呼叫者令為this,誰呼叫 誰就是this

但定義 arrow function 時不會有這個流程
因此在其中使用this時,指的便會是外層所使用的 global this,在 HTML 裡就是 window

例如上述的例子:我們只要把this改成IconDisplayer就可以了

1
2
3
display: () => {
if (currency === 'USD') { return (this.Current.USD) }
}

不然就要用傳統函式:

    display: function(){
      if (currency === 'USD') { return (this.Current.USD) }
    }

結語

曾經看到有人說應該要把 arrow function 視為獨立的新語法,而不是傳統function 的變化,因為有時運作方式是截然不同,今天更能體會到這點了!
最後,今天的重點:

this 的值只跟「你如何呼叫、誰呼叫」有關,與程式碼位於哪裡完全無關

參考:iT邦幫忙

有了登入功能後,我們可能會希望儲存用戶的資料

無論是個人資料(頭像、帳號名、電話、信箱等等)
或是其他隨時間變多的資料,像是個人貼文

每發一篇貼文,我們就要把它記錄在資料庫裡
他可能需要建立在 users 的節點之下
也可以建立在 post 節點之下
或同時在多個節點做更新

這篇文章會告訴你 Firebase Realtime Database 的一些簡單操作:

1. 寫入 set()push()

2. 讀取 on()get()

3. 更新 update()

4. 刪除 delete()

在開始前,別忘了到 firebase console 啟用 realtime database

取得 reference

每次更動資料時
需要告訴程式你想要處理資料庫中什麼位置的資料

這個位置就叫做 firebase.database.Reference
可藉由ref()定義

1
const Ref = firebase.database().ref()

ref()可傳入 path,如:

1
2
3
const user = firebase.auth().currentUser
const userRef = firebase.database().ref('/users/'+ user.uid)

對於任一個 Reference
你可以用 child() 來得到下層的 Reference
假如我們要到 /user/user.uid/hobby/

1
const userHobbyRef = userRef.child('hobby')

取得 Reference 後在後面掛上函數就能變更資料了

寫入資料

set()

最簡單的方式
我們可以用set()來寫入資料

1
2
3
4
5
6
userRef.set({
name:'Tony',
age:24
hobby:['tennis','coding','eating']
timeStamp: Date.now()
})

set()函數會直接複寫該節點的資料,包括所有子節點

push()

除此之外
我們也能用 push()
帶入參數,就會在該節點的 last space 建立資料
不帶入也可以,就不會寫入
而後回傳該處的 Ref

1
2
3
4
5
6
7
8
const postListRef = firebase.database().ref('/posts/')

//保留 Ref 以便之後使用
const newPostRef = postListRef.push()
newPostRef.set('New Post')

// 直接寫入
postListRef.push('New Post')

無論如何,push()都會產生一個key
這個 key 是依 timestamp 隨機產生的
也因此push()適合有多個用戶的 app 使用
避免同時接收多個寫入指令,造成問題

要取得key值,可使用.key

1
const newPostKey = postListRef.push().key

讀取資料

on()

要讀取資料,官方最推薦的方式是on()

1
2
3
4
5
// userRef.on(eventtype,callback(snap))

userRef.on('value', (snap)=>{
setUserEmail(JSON.stringify(snap.child('user_email').val()))
})

給予一個 Ref,on()會建立一個 listener

第一個參數'value'指的是只要這個 Ref 以下任何 value 發生變化時就會觸發 callback function (第二個參數)
其他還有

  • 'child_added'
  • 'child_changed'
  • 'child_removed'
  • 'child_moved'

第二個參數是 callback,傳入 snap
這個 snap 的模樣會是該節點變更後的資料
記得要做JSON.stringfy()
並用val()取得數值

就我嘗試的結果
on()需要放在 useEffect() 裡面

get()

如果你不需要監聽,只需取得資料一次
可以使用get()

1
2
3
4
userRef.get()
.then()
.catch()
// return a Promise (dataSnapshot or rejection)

根據官方說法,過多的get()會導致效能問題
因此確保你只在需要的地方使用get()
on()才是預設選項

更新資料

update()

update()函數讓你能以一次呼叫,更改資料庫的多個地方
第一個參數是object
其中的 child property 可以填入 simple property

1
2
3
4
var adaNameRef = firebase.database().ref('users/ada/name');
// Modify the 'first' and 'last' properties, but leave other data at
// adaNameRef unchanged.
adaNameRef.update({ first: 'Ada', last: 'Lovelace' });

或是 path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var ref = firebase.database().ref()
// Generate a new push ID for the new post
var newPostRef = ref.child("posts").push();
var newPostKey = newPostRef.key();
// Create the data we want to update
var updatedUserData = {};
updatedUserData["user/posts/" + newPostKey] = true;
updatedUserData["posts/" + newPostKey] = {
title: "New Post",
content: "Here is my new post!"
};
// Do a deep-path update
ref.update(updatedUserData, function(error) {
if (error) {
console.log("Error updating data:", error);
}
});

第二個參數是 callback 並帶入 error

參考 Multi-location updates

刪除資料

delete()

1
2
Ref.Remove()
// return a Promise