useReducer
may be used as an alternative to useState
.
const [state, dispatch] = useReducer(reducer, initialState, lazyInitFunction)
Ideal for complex state logic where there's a dependency on previous state values or a lotta state sub values
const initialState = { 15 }
const reducer = (state, action) => {
switch (action) {
case 'plus':
return { state.width + 15 }
case 'minus':
return { Math.max(state.width - 15, 2) }
default:
throw new Error("what's going on?" )
}
}
const Bar = () => {
const [state, dispatch] = useReducer(reducer, initialState)
return <>
<div style={{ background: 'teal', height: '30px', state.width }}></div>
<div style={{marginTop: '3rem'}}>
<button onClick={() => dispatch('plus')}>Increase bar size</button>
<button onClick={() => dispatch('minus')}>Decrease bar size</button>
</div>
</>
}
render(Bar)
以lazy函数返回设置初始状态
const initializeState = () => ({
100
})
// ✅ note how the value returned from the fn above overrides initialState below:
const initialState = { 15 }
const reducer = (state, action) => {
switch (action) {
case 'plus':
return { state.width + 15 }
case 'minus':
return { Math.max(state.width - 15, 2) }
default:
throw new Error("what's going on?" )
}
}
const Bar = () => {
const [state, dispatch] = useReducer(reducer, initialState, initializeState)
return <>
<div style={{ background: 'teal', height: '30px', state.width }}></div>
<div style={{marginTop: '3rem'}}>
<button onClick={() => dispatch('plus')}>Increase bar size</button>
<button onClick={() => dispatch('minus')}>Decrease bar size</button>
</div>
</>
}
render(Bar)
模拟this.setState的merge行为
const initialState = { 15 }
const reducer = (state, newState) => ({
...state,
newState.width
})
const Bar = () => {
const [state, setState] = useReducer(reducer, initialState)
return <>
<div style={{ background: 'teal', height: '30px', state.width }}></div>
<div style={{marginTop: '3rem'}}>
<button onClick={() => setState({ 100})}>Increase bar size</button>
<button onClick={() => setState({ 3})}>Decrease bar size</button>
</div>
</>
}
render(Bar)