在今天的文章中,我们将会使用 Redux 去完成一个计数器的范例程序。
使用 createStore 建立一个 Redux store ,并将 store 用 react-redux 的 Provider 元件提供给 React 的母元件 App
// store/index.js
import { createStore } from 'redux';
const counterReducer = (state = { counter: 0 }, action) => {
if (action.type === 'increment') {
return { counter: state.counter + 1 };
}
if (action.type === 'decrement') {
return { counter: state.counter - 1 };
}
return state;
};
const store = createStore(counterReducer);
export default store;
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './store/index';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
在元件使用 useSelector 和 useDispatch 这两个 hook ,这边介绍一下这两个 hook 的用法:
使用这个 hook 可以从 store 里面去拿取想要的 state 出来,效用大致等於 connect 元件的 mapStateToProps。
ex:
const counter = useSelector(state => state.counter);
透过这个 hook 会回传一个 dispatch 方法,可以让我们 dispatch actions,用来取代 mapStateToDispatch。
const dispatch = useDispatch();
另外还有一个 hook useStore,不过我们暂时不会用到,但还是介绍一下,它可以取得 store,并进行 getState()、subscribe() 、dispatch() 等函式呼叫。
const store = useStore();
在程序码中可以看到使用 useSelector 去取出 store 里面的 counter state,并透过 useDispatch 回传的 dispatch 方法去触发 reducer。
// Counter.js
import { useSelector, useDispatch } from "react-redux";
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector((state) => state.counter);
const incrementHandler = () => {
dispatch({ type: "increment" });
};
const decrementHandler = () => {
dispatch({ type: "decrement" });
};
return (
<>
<div>{counter}</div>
<button onClick={incrementHandler}>Increment</button>
<button onClick={decrementHandler}>Decrement</button>
</>
);
};
export default Counter;
完成以上程序码的实作後,就可以点击按钮做加减了。
接着我们多加一个 toggle 按钮及一个点击一次就增加多个数字的按钮。
// store/index.js
import { createStore } from 'redux';
const initialState = { counter: 0, showCounter: true };
const counterReducer = (state = initialState, action) => {
if (action.type === 'increment') {
return {
counter: state.counter + 1,
showCounter: state.showCounter
};
}
if (action.type === 'increase') {
return {
counter: state.counter + action.amount,
showCounter: state.showCounter
};
}
if (action.type === 'decrement') {
return {
counter: state.counter - 1,
showCounter: state.showCounter
};
}
if (action.type === 'toggle') {
return {
showCounter: !state.showCounter,
counter: state.counter
};
}
return state;
};
const store = createStore(counterReducer);
export default store;
// Counter.js
import { useSelector, useDispatch } from "react-redux";
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector((state) => state.counter);
const show = useSelector((state) => state.showCounter);
const incrementHandler = () => {
dispatch({ type: "increment" });
};
const increaseHandler = () => {
dispatch({ type: "increase", amount: 10 });
};
const decrementHandler = () => {
dispatch({ type: "decrement" });
};
const toggleCounterHandler = () => {
dispatch({ type: "toggle" });
};
return (
<>
{show && <div>{counter}</div>}
<button onClick={incrementHandler}>Increment</button>
<button onClick={increaseHandler}>Increase by 10</button>
<button onClick={decrementHandler}>Decrement</button>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</>
);
};
export default Counter;
到这边实作就完成了!实作的程序码范例在底下连结,明天将会介绍另一种撰写 Redux 的 library: Redux toolkit。
这里补充一个管理多个 Reducer 的范例:
程序码范例
在范例中,可以看到 dispatch({ type: "increase", amount: 10 });
等 action 物件,如果在多个地方使用的话就得重复去撰写同样的 action,所以可以建立一个 action creator 的函式,如果有多个地方同时去使用相同的 action,就只要去呼叫已经定义好 action 结构的该函式即可。
const increaseByNum = (num) => {
return {
type: "increase",
amount: num
};
};
<button onClick={() => dispatch(increaseByNum(10))}>Increase by 10</button>
<<: 树状结构转线性纪录再转二元树-孩子兄弟标记法 - DAY 15
>>: Day15|【Git】git reset 补充 - 三种模式
安装Python 既然是用 Python 编写的框架,那理所当然的应该先建立 Python 的环境对...
为了不让队友 panic,先发文,正在修改,有兴趣可以明日观看。 1.1 Introduction ...
昨天跟大家介绍完middleware的基本建立後,大家有没有理解并成功做出来呢! 如果对於这部分还有...
天亮了 昨晚是平安夜 关於迷雾森林故事 苏醒 在发牌之前我们先稍微小小调整一下房间的介面 我对你 想...
架构图 创建工程 首先我们先创建一个资料夹example,路径最好配置为全英文,然後分别在examp...