前情提要:在前面的文章有了Redux,状态管理没烦恼,学到了如何在 Redux 透过 Action 管理更新所有的 State。接下来就让我们学习如何在 React 中使用 Redux 来处理资料状态。
Redux 是一个独立的状态管理函式库,它可以搭配原生 Javascript 直接撰写出一个应用程序,也可以与其他框架像是 React、Angular 一起运作。而当 Redux 与 React 结合时,会使用 React-redux 这个延伸的函式库,有效的来解决 React Component 间 State 复杂化的问题。
Fork 一份之前所使用的React - 计时器范例程序码,基於这个架构从头来使用 React-redux。
React-redux 前面建置步骤基本上跟单纯使用 Redux 一样,要事先建立 Action、Reducer、Store,所以我们直接贴上前篇建立好的三份程序码 actions.js、reducer.js、store.js,里面包含了 Redux 应用在计数器的内容。
actions.js
export const ADD_SCORE = "ADD_SCORE";
export const REDUCE_SCORE = "REDUCE_SCORE";
// action creator
export function addScore(idx) {
return {
type: ADD_SCORE,
payload: { idx }
};
}
export function reduceScore(idx) {
return {
type: REDUCE_SCORE,
payload: { idx }
};
}
reducer.js
import { ADD_SCORE, REDUCE_SCORE } from "./actions";
const initialState = {
members: [
{ name: "May", score: 0 },
{ name: "Julia", score: 0 },
{ name: "Selina", score: 0 }
]
};
export default function appReducer(state = initialState, action) {
switch (action.type) {
case ADD_SCORE: {
let new_members = state.members;
new_members[action.payload.idx] = {
...new_members[action.payload.idx],
score: new_members[action.payload.idx].score + 1
};
return {
members: new_members
};
}
case REDUCE_SCORE: {
let new_members = state.members;
new_members[action.payload.idx] = {
...new_members[action.payload.idx],
score: new_members[action.payload.idx].score - 1
};
return {
members: new_members
};
}
default:
return state;
}
}
store.js
import { createStore } from "redux";
import rootReducer from "./reducer";
const store = createStore(rootReducer);
export default store;
接着就让我们正式将 React 与 Redux 结合,我们首先要做的就是让 React Component 知道 Store,才能读取资料和调用动作,所以就透过在 Root component 使用 <Provider>
的方式来传递 Store。
...
import { Provider } from "react-redux";
import store from './store'
ReactDOM.render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
rootElement
);
要从 Store 读取状态,可以使用 useSelector
这个方法,直接提取 Redux Store 中的状态数据到指定的元件中。并且它会对之前的选择器回传值和当前的回传值进行比较,如果不同,相关的组件就会重新渲染。
App.js
import { useSelector } from "react-redux";
export default function App() {
const members = useSelector((state) => state.members);
return (
<div className="App">
...
{members.map((member) => (
<Member key={member.name} idx={index} />
))}
</div>
);
}
Member.js
...
import { useSelector } from "react-redux";
export default function Member(props) {
const members = useSelector((state) => state.members);
return (
<div className="member">
<h2>{members[props.idx].name}</h2>
<div>{members[props.idx].score > 0 ? "PASS" : "FAIL"}</div>
<Counter idx={props.idx} />
</div>
);
}
Counter.js
import { useDispatch, useSelector } from "react-redux";
import { addScore, reduceScore } from "../actions";
export default function Counter(props) {
const score = useSelector((state) => state.members[props.idx].score);
return (
<div className="Counter">
<h3>{score}</h3>
...
{score > 0 && (
<button>minus</button>
)}
</div>
);
}
完成从 Store 读取资料状态後,最後一个步骤就是要可以在组件中调用动作,来修改 State 的值。我们可以透过 useDispatch()
这个方法,发动指定的 Action 到 Reducer 中更新 State。
Counter.js
...
import { useDispatch, useSelector } from "react-redux";
import { addScore, reduceScore } from "../actions";
export default function Counter(props) {
const score = ...
const dispatch = useDispatch();
return (
<div className="Counter">
...
<button onClick={() => dispatch(addScore(props.idx))}>Plus</button>
{score > 0 && (
<button onClick={() => dispatch(reduceScore(props.idx))}>minus</button>
)}
</div>
);
}
在 React 中使用 Redux 的 React-redux 基本上就是这样运作的,以往在 React 中需要透过提升 State 层级才能在 Component 间共同使用状态,结合 Redux 集中状态管理的功能,就能有效的管理复杂的 State,弥补了 React 框架的缺点更提升它的优势。
如果文章中有错误的地方,要麻烦各位大大不吝赐教;喜欢的话,也要记得帮我按赞订阅喔❤️
<<: Day 23 | 在Flutter里串接restful api - 我不使用HttpClient了 jojo
Golang 玩一下html template 如果golang要使用作为网站的话,不太可能都只靠p...
前几天介绍的 MVVM 架构,可以参考这篇 [[Android APP] 01-架构介绍-MVVM]...
在AWS solutions library你可以找到数十份各式各样的解决方案参考文件,在这个解决方...
数位 I/O 视窗当然是要有数位讯号相关功能啦。 数位 I/O 功能 在 Supported Mod...
啊..败给旅游燃烧殆尽症候群了,昨天晚上不小心睡着,忘记设闹钟,再醒来就已经过12点了QwQ ...