今日關鍵字:redux
當初資料格式裡面有這兩個屬性
isFavorite: boolean
isReminding: boolean
對應著是否加入我的最愛及開啟提醒
今天先來使按鈕能正常發亮變暗吧
首先先幫細節頁面新增愛心跟鈴鐺兩個按鈕
...
<TouchableOpacity activeOpacity={1}>
<Ionicons
style={{
...
color: anime.isReminding ? 'tomato' : 'black'
}}
name={
anime.isReminding ? iconType('heart') : iconType('heart-outline')
}
color="#000"
size={24}
onPress={() => {
}}
/>
</TouchableOpacity>
<TouchableOpacity activeOpacity={1}>
<Ionicons
style={{
...
color: anime.isFavorite ? 'tomato' : 'black'
}}
name={
anime.isFavorite ? iconType('heart') : iconType('heart-outline')
}
color="#000"
size={24}
onPress={() => {
}}
/>
</TouchableOpacity>
...
依據isFavorite
及isReminding
的值圖標的樣式和顏色會有變化
根據day10的最後
點進細節頁面時
<AnimeDetail animeIndex={props.route.params!.anime} />
是把整個動畫物件傳了進來
那渲染細節頁面時要直接使用這個物件嗎?
由於現在的資料統一放在redux中
當我們等等寫一些action觸發狀態改變時
這樣寫無法即時接收狀態更新(也就是說點了愛心後圖標不會即時變色)
我承認我先這樣寫過了
因此這裡我決定只拿傳進來的動畫的id來用
先把所以動畫的資料以useSelector
從store中獲得
再以id比對的方式尋找對應的資料
...
import { useSelector } from 'react-redux'
...
const AnimeDetail = ({ animeIndex }: AnimeDetailProps) => {
...
const allAnime = useSelector((state: RootStateType) => state.allAnime)
const anime = useMemo(() => {
for (let i = 0; i < allAnime.length; i += 1) {
if (allAnime[i].id === animeIndex.id) {
return allAnime[i]
}
}
return animeIndex
}, allAnime)
...
為了減少運算,當store上的狀態未改變時不觸發重新尋找資料的動作
接收完狀態後,該來寫新的action來觸發狀態變化了
// action.ts
export const RENEW_DATA = 'RENEW_DATA'
export const renewData = (anime: Anime) => ({
type: RENEW_DATA,
payload: {
anime
}
})
由於以後還可能有其他更新資料
這裡將整個更改後的物件作為參數傳遞
reducer
內則比對id
然後將資料更改對應的資料後回傳新陣列
// reducer.ts
const allAnimeCopy = [...state]
switch (action.type) {
...
case animeActions.RENEW_DATA:
for (let i = 0; i < state.length; i += 1) {
if (action.payload!.anime!.id === allAnimeCopy[i].id) {
allAnimeCopy[i] = action.payload!.anime!
}
}
return allAnimeCopy
由於剛剛已經寫好接收狀態的動作
所以觸發action後細節頁面已經接收最新的狀態了
最後一步就是在細節頁面點擊按鈕時觸發action
// AnimeDetail.tsx
...
import { useDispatch, useSelector } from 'react-redux'
// import剛寫好的action
import { renewData } from '../../redux/action/animeAction'
const AnimeDetail = ({ animeIndex }: AnimeDetailProps) => {
const dispatch = useDispatch()
...
<TouchableOpacity activeOpacity={1}>
<Ionicons
...
onPress={() => {
const animeCopy = { ...anime }
animeCopy.isFavorite = !animeCopy.isFavorite
dispatch(renewData(animeCopy))
}}
/>
</TouchableOpacity>
...
這樣就能將幫喜歡的動畫點愛心了
明天預計來寫在App內開啟網頁
然後今天就是延續day10,redux的基本操作,所以沒有參考啦