繼昨天 export 之後我們就可以來撰寫 reducer。把 NEW_MEME
加進來
import { RECEIVE_MEMES, NEW_MEME } from '../actions';
接下來要寫 reducer 回調函數,我們要回傳兩個參數 State
和 Action
,透過 action 的 type 決定接下來的動作。當 action type = NEW_MEME 時,便更新 state 的內容。
function myMemes(state = [], action){
switch(action.type) {
case NEW_MEME:
state = [...state, action.meme],
return state;
default:
return state;
}
}
記得要將剛剛新增的 myMemes 加到 combineReducer function 中,接下來要把 myMemes 的 action creator 加在 MemeItem component 之上,它允許我們把 meme actions 的 creation 附加到我們之前寫好的 postMeme
function。進到 MemeItem.js
把 newMeme
這個 action import 進來
import { newMeme } from '../actions';
我們必須把我們的 component 和 redux 做連結,因此這邊把 connect function
引進來
import { connect } from 'react-redux';
export 的地方也要加上 connect,不過現在還沒有 state props 因此先給 null
export default connect(null, {newMeme})(MemeItem);
在 postMeme function 裡,我們要把 this.props
的值傳進去,透過 const 我們可取得 text0 和 text1 變數
postMeme(){
const { text0, text1 } = this.props;
}
現在,我們建造一個 meme object,這個物件裡面包含 meme id
以及 input value
(也就是 text0,text1 的值)
椰絲!現在可以看到 console.log 有抓到 text0
,text1
,template_id
的值!!!
GETTING CLOSER!!!
創建一個 postMemeJson
function
function postMemeJson(params){
}
這個階段,我們需要身份驗證資訊才有辦法從 API 中再次取出圖片,所以必須把 secrets.js
裡面定義的 API 的帳號與密碼引入,這在後面產出 meme 時,可以讓這些 object 包含我的帳號與密碼(import 要寫在最前面)
import { username, password } from './secrets';
要進到 API 必須要有一組特殊 url code,因此我們要把我們的 params
調整成符合的 body string。Object.key(params)
會取的所有 params 裡的 key 值,map 每一個 key 並產出一個 encode 結果,中間用 =
去和 API 裡的 key 值比對,這樣的寫法就可以取得 encode 後的 URL。.join('&');
可以把每一個屬性值用 &
區隔開來。
function postMemeJson(params){
params["username"] = username;
params["password"] = password;
const bodyParams = Object.key(params).map(key => {
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key])
}).join('&');
}
現在我們準備好可以呼叫 fetch function 了,fetch 方法幫我們抓取到與 fetch meme json function 裡相同的 url。我們必須定義我們要用的是 POST
方法,並且定義這個方法的內容,也就是 'application/x-www-form-urlencoded'
。在 POST 裡,header
是允許我們定義要傳進 API 的特定規範。透過 .then()
回傳 json
return fetch('https://api.imgflip.com/caption_image',{
method: "POST",
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: bodyParams
}).then(response => response.json());
接下來要新增 createMeme function,把 new_meme_object
傳回 postMemeJson
,接著我們要用 new_meme action creater
dispatch 從 handler 傳過來的 new_meme
export function createMeme(new_meme_object){
return function(dispatch){
return postMemeJson(new_meme_object)
.then(new_meme => dispatch(newMeme(new_meme)))
}
}
接著更新 MemeItem component
裡的 newMeme,改用 createMeme
取代它
import { createMeme } from '../actions';
postMeme(){
const { text0, text1 } = this.props;
const memeObj = {
template_id : this.props.meme.id,
text0,
text1
}
this.porps.createMeme(memeObj);
}
椰乎!在 myMemes
裡看到我輸入的文字以及新產生的 url,success: true
表示成功!
我把 url 單獨開啟分頁,瓦~~~哈哈哈哈這臉神韻完全發揮得淋漓盡致XDDDD
熬了真久~終於來到最最後一個步驟啦!因為使用者並不會自己開啟 console.log 尋找他自己做的 memes 的網址(除了很懂網頁機關的各位可能會XD)
我接下來要讓這個圖片直接呈現在頁面上~
剛剛我們的 array 取名叫 Mymemes
,那麼我就來新增一個 Mymemes component
建立 MyMeme 類別
class MyMemes extends Component{
return (){
<div>
{
this.props.myMemes.map((meme, index) => {
return(
<img
key={index}
src={meme.data.url}
alt="my-meme"
className="my-meme-img"
/>
)
})
}
</div>
}
}
讓 memes 透過 prop 更新 state
function mapStateToProps(state){
return {
myMemes: state.myMemes
}
}
export connect
export default connect(mapStateToProps, null)(MyMemes);
最後,到 parent component App.js
加上 MyMeme tag,加在標題下方
import MyMemes from './MyMemes';
<h2> Welcome to the Meme Generator!</h2>
<MyMemes />
yaaaaaaaaaaaaaaaa
yoooooooooooooooo
有哩
完整專案連結 Github