繁体   English   中英

使用 React Hooks 设置 state 的正确方法是什么?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM