[英]What is the proper way to set state with React Hooks?
我最近问了一篇关于useState()
进行 2 次点击的Stack Overflow 帖子。 我被告知我可以通过执行setState(state => !state)
立即更新 boolean state 。 但是,这仅适用于布尔值。 举个例子:
let [popularQuotes, setPopularQuotes] = useState([])
let [newQuotes, setNewQuotes] = useState([])
let [selected, select] = useState("popular")
const getQuotes = async() => {
Post('https://example.com/api/quotes', {
sort: selected
}).then((r) => selected == "popular" ? setPopularQuotes(r) : setNewQuotes(r))
}
当我想从流行语录切换到新语录时,例如onClick={() => {select("popular"); getQuotes()}}
onClick={() => {select("popular"); getQuotes()}}
,它需要点击 2 次,因为 state newQuotes
在第一次点击时最初保持不变(只是一个空数组)。 我该如何解决这个问题并在第一次点击时更新 state?
将这样的效果挂钩添加到您的 function 组件主体,以便在selected
更改时触发 Api:
useEffect(() => {
getQuotes(selected);
},[selected]);
更改getQuotes
以获取selected
值作为参数:
const getQuotes = async(selectedItem) => {
Post('https://example.com/api/quotes', {
sort: selectedItem
}).then((r) => selectedItem == "popular" ? setPopularQuotes(r) : setNewQuotes(r))
}
最后修改onClick
回调如下:
onClick={() => select("popular")}
您遇到的事实是设置 state 是异步的,因此 -
onClick={() => {select("popular"); getQuotes()}}
将不会调用getQuotes
并将“selected”的更新值设为“popular”
我建议您要么处理 state 中当前需要的报价,然后让 effect 处理 API 调用,但是如果您的组件结构不佳且不纯净,请小心,否则您最终可能会收到比您希望的更多的 API 调用-
const [popularQuotes, setPopularQuotes] = useState([])
const [newQuotes, setNewQuotes] = useState([])
const [selected, select] = useState("popular")
const getQuotes = async(selected) => {
Post('https://example.com/api/quotes', {
sort: selected
}).then((r) =>
selected === "popular" ?
setPopularQuotes(r) : setNewQuotes(r))
)
}
useEffect(() => {
getQuotes(selected);
}, [getQuotes, selected])
...
或者将报价类型作为参数传递给getQuotes
,并在 state 中跟踪先前请求的报价类型 -
let [selected, select] = useState("popular")
...
onClick={() => {
getQuotes(selected === 'popular' ? 'new' : 'popular');
select("popular");
}}
尽管这很难维护,因为您的 state 需要明确定义它是存储下一个要调用的 state 还是当前显示的那个,因此getQuotes
需要采取相反的行动
正如您在问题中提到的,您需要使用回调更新 state。
在下面的示例中,我使用以前的 state 值,但这不是强制性的。
const [someState, setSomeState] = useState({id: 'idA', name: 'someNameA'}) setSomeState(prevState => ({id: prevState.id + 'B', name: prevState.name + 'B'}));
可以在此处找到更多信息: useState set method is not reflecting a change immediately
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.