使用useReducer
还有另外一种解决方案!首先,我们定义我们的新setState
。
const [state, setState] = useReducer(
(state, newState) => ({...state, ...newState}),
{loading: true, data: null, something: ''}
)
之后我们可以像使用好用的老式类一样简单地使用它 this.setState
,只是不需要this
了!
setState({loading: false, data: test.data.results})
正如您可能已经注意到的那样,在我们的新setState
中(就像之前我们使用的this.setState
一样),我们不需要同时更新所有状态!例如,我可以像这样更改其中一个状态(而它不会改变其他状态!):
setState({loading: false})
太棒了,哈?!
那么让我们把所有的部分组合在一起:
import {useReducer} from 'react'
const getData = url => {
const [state, setState] = useReducer(
(state, newState) => ({...state, ...newState}),
{loading: true, data: null}
)
useEffect(async () => {
const test = await api.get('/people')
if(test.ok){
setState({loading: false, data: test.data.results})
}
}, [])
return state
}
Typescript支持。
感谢P. Galbraith提供的解决方案,
使用Typescript的人可以使用以下代码:
useReducer<Reducer<MyState, Partial<MyState>>>(...)
其中 MyState
是你的状态对象的类型。
例如,在我们的情况下,它会像这样:
interface MyState {
loading: boolean;
data: any;
something: string;
}
const [state, setState] = useReducer<Reducer<MyState, Partial<MyState>>>(
(state, newState) => ({...state, ...newState}),
{loading: true, data: null, something: ''}
)
之前的状态支持。
在评论中,user2420374 请求一种方法,可以在我们的 setState
中访问 prevState
,所以这里提供了一种实现此目标的方法:
const [state, setState] = useReducer(
(state, newState) => {
newWithPrevState = isFunction(newState) ? newState(state) : newState
return (
{...state, ...newWithPrevState}
)
},
initialState
)
setState(prevState => {...})
isFunction
检查传递的参数是否为函数(这意味着您正在尝试访问 prevState)或普通对象。您可以在Alex Grande在此处实现的 isFunction中找到它。
注意。对于那些想要经常使用此答案的人,我决定将其转化为一个库。您可以在此处找到它:
Github: https://github.com/thevahidal/react-use-setstate
NPM: https://www.npmjs.com/package/react-use-setstate
useReducer
。 - thinklinuxsetX
函数时发生。来源:https://github.com/facebook/react/issues/14259#issuecomment-439632622,https://blog.logrocket.com/simplifying-state-management-in-react-apps-with-batched-updates/ - allieferruseReducer
或redux-toolkit
。 - Aman Ghanghoriya