useReducer是redux的hooks用法,直接通过demo演示。
components目录下新建ReducerDemo.js:
import React, { } from 'react';
export default function ReducerDemo(props) {
return (
<div> reducer</div>
);
}
在App.js中引入:
...
import ReducerDemo from "./components/ReducerDemo";
function App() {
const [isVisible, setIsVisible] = useState(true);
return (
<div>
...
<ReducerDemo />
</div>
);
}
export default App;
现在根据官方的demo开始改写ReducerDemo.js:
import React, { useReducer } from 'react';
export default function ReducerDemo(props) {
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div> reducer count:{state.count} <br/>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</div>
);
}
页面效果:
这样就实现了useReducer最基本的用法。
如果希望每次加2,就可以增加参数payLoad:
import React, { useReducer } from 'react';
export default function ReducerDemo(props) {
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + action.payLoad };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div> reducer count:{state.count} <br/>
<button onClick={() => dispatch({type: 'increment', payLoad: 2})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</div>
);
}
精简一点:
import React, { useReducer } from 'react';
export default function ReducerDemo(props) {
const initialState = { count: 0 };
function reducer(state, action) {
const {type, payLoad = 1} = action;
switch (type) {
case 'increment':
return { count: state.count + payLoad };
case 'decrement':
return { count: state.count - payLoad };
default:
throw new Error();
}
}
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div> reducer count:{state.count} <br/>
<button onClick={() => dispatch({type: 'increment', payLoad: 2})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</div>
);
}
假如再有一个state需要改变(...表省略):
import React, { useReducer } from 'react';
export default function ReducerDemo(props) {
const initialState = { count: 0, name: 'zhangsan' };
function reducer(state, action) {
const {type, payLoad = 1} = action;
switch (type) {
...
case 'rename':
return {name: payLoad};
default:
throw new Error();
}
}
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div> reducer count:{state.count} and name: {state.name} <br/>
...
<button onClick={() => dispatch({type: 'rename', payLoad: 'lisi'})}>rename</button>
</div>
);
}
点击rename后count值消失了:
再点击+count显示NaN,name也不见了:
这里就说明reduce里return的必须是和initialState同结构的对象,把return里的对象前面加上一个state拓展运算就好了(保留state里没变的key-value,变动的额外声明):
case 'increment':
return {...state, count: state.count + payLoad };
case 'decrement':
return {...state, count: state.count - payLoad };
case 'rename':
return {...state, name: payLoad};
default:
小tip:按传统的redux写法,最好把reducer和actionType单独写成文件的。