React.js筆記:React Redux Hooks
在React Redux v7.1.0中首次加入了屬於React Redux的custom Hooks API,個人認爲比原來的connect()、mapStateToProps等Function好理解多,要使用相關套件前記得都要確認版本。
npm install react-redux@7.1.0
以上圖簡單情景爲例,建立單純的Reducer,資料都是直接Hard code:
// src/reducers/index.js
import { combineReducers } from "redux";
const songsReducer = () => {
return [
{
title: "Bitchin' Summer",
artist: "Avril Lavigne",
duration: "3:32",
favourite: false,
},
{
title: "勘冴えて悔しいわ",
artist: "ずっと真夜中でいいのに。",
duration: "4:03",
favourite: true,
},
{
title: "絶対にチョコミントを食べるアオイチャン",
artist: "GYARI",
duration: "5:56",
favourite: false,
},
{
title: "夜明けの歌",
artist: "M2U x ダズビー",
duration: "3:16",
favourite: true,
},
];
};
const selectedSongReducer = (selectedSong = null, action) => {
if (action.type === "SONG_SELECTED") return action.payload;
return selectedSong;
};
export default combineReducers({
songs: songsReducer,
selectedSong: selectedSongReducer,
});
然後跟Class-based的React Redux一樣,src目錄中的index.js需要import Provider和createStore並以Provider tag包住App Component:
// src/index.js
import React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import App from "./components/App";
import reducers from "./reducers";
render(
<Provider store={createStore(reducers)}>
<App />
</Provider>,
document.querySelector("#root")
);
Action creator,需要配搭dispatch方法更新Store存放的State:
// src/actions/index.js
// Action creator
export const selectSong = (song) => {
// Return an action
return {
type: "SONG_SELECTED",
payload: song,
};
};
基本的配置完成!以上的做法都跟Class-based的React Redux一模一樣。
在情景中我們還需要建立App Component以及SongList Component,App Component只負責統整所有Component再交給ReactDOM render,故此也程式碼跟最基本的Functional Component沒差多少,會有nested div以及className等只是因爲此例以Semantic UI作爲Styling:
// src/components/App.js
import React from "react";
import SongList from "./SongList";
const App = () => {
return (
<div className="ui container grid">
<div className="ui row">
<div className="column eight wide">
<SongList />
</div>
</div>
</div>
);
};
useSelector以及useDispatch
比較需要說明的是SongList Component,以React Redux v7.1.0的useSelector可以簡單地將Component需要的state從Store中取出來。不再需要經過connect() 方法,所以mapStateToProps方法也不用寫了;因爲這邊只有songs和selectedSong兩個state,我們不使用destructor直接提取state也是可以:
const SongList = () => {
const state = useSelector((state) => state);
console.log(state);
...
}
這裏我們把state console.log出來看看:
出來的結果跟使用mapStateToProps一樣,但程式碼短得多了!
同樣新版本也不再需要以mapDispatchToProps + dispatch方法來觸發Reducer,React Redux v7.1.0提供了Hooks API(useDispatch)來直接回傳dispatch方法,此例我們的button onClick事件便會呼叫dispatch來觸發Reducer
const dispatch = useDispatch();
...
//
<button
onClick={() => {
// dispatch an action
dispatch(selectSong(song));
}}
className="ui right floated button primary"
>
Select
</button>
按下Button便會促使SongList Component重新render,可以透過console.log看到state中的selectedSong已經更新成所選的歌曲:
簡單兩個Hooks ,就能完成提取Store中的state和觸發Reducer,程式碼還更簡潔直覺。
完整程式碼:
import React from "react";
import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { selectSong } from "../actions";
const SongList = () => {
// useSelector: essentially identical to the mapStateToProps function
// which extract the Redux store's state to this component props
// using the useSelector Hook eliminated the need of connect()
const state = useSelector((state) => state);
console.log(state);
const dispatch = useDispatch();
const renderList = () => {
return state.songs.map((song) => {
// return some jsx element
return (
<div className="item" key={song.title}>
<div className="content">
<button
onClick={() => {
// dispatch an action
dispatch(selectSong(song));
}}
className="ui right floated button primary"
>
Select
</button>
{song.favourite && <i className="yellow star icon"></i>}
{song.title}
</div>
</div>
);
});
};
return <div className="ui divided items">{renderList()}</div>;
};
export default SongList;
搞懂React、Redux、Middleware:
100 行秒懂 React、Redux、Middleware
Day 27: Redux篇 - 使用react-redux綁定Redux與React - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天