ReactJS - 新的 useState React 钩子中的 prevState?
Posted
技术标签:
【中文标题】ReactJS - 新的 useState React 钩子中的 prevState?【英文标题】:ReactJS - prevState in the new useState React hook? 【发布时间】:2019-09-13 08:26:57 【问题描述】:我真的很喜欢新的React hooks,并且我经常将它们用于我正在进行的项目。我遇到了一种情况,我想在 useState
挂钩中使用 prevState,但我不确定如何执行此操作。
我尝试过类似的方法,但编译失败。
const [ someState, setSomeState ] = useState( new Map() )
setSomeState( prevState.someState.set( key, value ) )
(顺便说一句,这是映射一组复选框以跟踪被选中的复选框)
我正在尝试遵循此示例 here,但未使用 setState
函数。
感谢您的帮助!
【问题讨论】:
【参考方案1】:来自useState
的state updater
提供了一个回调模式,它返回您可以用来更新当前状态的先前状态
const [ someState, setSomeState ] = useState( new Map() )
setSomeState(prevState => prevState.set( key, value ) )
【讨论】:
嘿,我已经尝试过了,我收到了这个错误Cannot read property 'set' of undefined
。 useState
钩子有限制吗?
您可能使用的是prevState.someState.set( key, value )
而不是prevState.set( key, value )
状态更新器参考:reactjs.org/docs/hooks-reference.html#usestate
只是为了确认:为什么使用回调中的状态而不是someState
?为了避免混乱的并发更新?我只是经常看到这一点,但从来没有出现过技术解释。
@EricBurel 您并不总是需要使用函数式 setState,但有时它确实很有用。 This post 解释了类组件的一些细节,但同样适用于功能组件。此外,使用钩子进行功能状态更新对于避免关闭问题也非常有用,因为可以保证为您提供最新状态【参考方案2】:
为了使用Maps,您需要在操作值之前克隆它。否则,它会改变原始的 Map
,而 React 无法处理可变的 state
。
const handleChange = useCallback(( target: name, checked ) =>
setCheckbox(prevState =>
return new Map(prevState).set(name, checked);
);
, []);
更新的工作示例:
【讨论】:
更新了答案以包含一个有效的Map
示例。虽然这可行,但它的性能可能不如其他替代方案(尤其是当 Map
变大时)。【参考方案3】:
对于对象,您可以使用扩展运算符在您的 setState
调用中使用 prevState
。
const [object, setObject] = useState(
firstKey: '',
secondKey: '',
);
setObject((prevState) => (
...prevState,
secondKey: 'value',
));
// object =
// firstKey: '',
// secondKey: 'value',
//
下面的 sn-p 显示了使用prevState
设置对象状态的示例。
const useState = React;
const Example = (title) =>
const initialState =
firstKey: 'empty',
secondKey: 'empty',
thirdKey: 'not empty',
const [object, setObject] = useState(initialState);
const withPrevState = () =>
setObject((prevState) => (
...prevState,
secondKey: 'not empty',
));
return (
<div>
<h5>Updates Second key to 'not empty'</h5>
<p>First key: object.firstKey</p>
<p>Second key: object.secondKey</p>
<p>Third key: object.thirdKey</p>
<button onClick=withPrevState>
Update with prevState
</button>
<button onClick=() => setObject(secondKey: 'not empty')>
Update without prevState
</button>
<button onClick=() => setObject(initialState)>
Reset
</button>
</div>
);
;
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
【讨论】:
我终于明白了如何在这个sn-p中使用这个prevstate。谢谢 我相信这会降低性能,因为 React 认为所有状态条目都设置为新的。此外,您正在克隆一个数组,这也可能导致具有许多条目的状态的性能急剧下降。【参考方案4】:你已经在被破坏的变量中拥有了之前的状态:someState
所以你可以这样做:
const [ someState, setSomeState ] = useState( new Map() )
setSomeState( someState.set( key, value ) )
【讨论】:
不了解 OP 但这解决了我面临的一个问题。谢谢。又聪明!【参考方案5】:使用这个
const [setSome, setSomeState] = useState(thing: 'loding', count: 1);
setSomeState(prev => (...prev, count: prev.count + 1));
【讨论】:
以上是关于ReactJS - 新的 useState React 钩子中的 prevState?的主要内容,如果未能解决你的问题,请参考以下文章
在 ReactJS 中删除项目,使用 useState 和 useContext