用React中的功能组件Hooks代替HOC setState和回调

时间:2020-06-03 15:55:39

标签: javascript reactjs

我刚刚开始使用React,并编写了一些HOC。然后我读到功能组件和挂钩是前进的建议方法,所以我决定重写我的HOC。

我使用的常见模式是:

class MyButton(Component) {
...
  handleClick = () => {
    setState({busy: True}, () => {
      fetchAPI().then(
        (results) => {
          setState({results: results, errs: [], busy: False});
        },
        (err) => {
          setState({errs: err, busy: False});
        });
    });
  };

  render() {
    return(
      <Button disabled={this.state.busy} onClick={this.handleClick} />
    )
  }
}

如果我理解正确,当我单击按钮时,它将禁用它,呈现禁用的按钮,然后从api获取内容,然后设置结果的状态(并启用按钮),然后呈现启用的按钮。

这将防止人们单击该按钮10次,在第一次完成操作之前10次点击api。

我该如何使用功能组件和挂钩? 我天真的实现方式是这样,但似乎不正确。

MyButton = (props) => {
  const [results, setResults] = useState([]);
  const [errs, setErrs] = useState([]);
  const [busy, setBusy] = useState(False);
  const handleClick = () => {
    setBusy(true);
    fetchAPI().then(
      (results) => {
        setResults(results);
        setErrs([]);
        setBusy(False);
      },
      (err) => {
        setErrs(errs);
        setBusy(False);
      });
    );
  }
  return (
    <Button disabled={busy} onClick={handleClick} />
  )
}

有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

一种简单的方法是将fetchApi写入useEffect钩子中,并且您的按钮会在何时激活此效果之间进行切换,如下所示。您还可以签出react-query库来执行此操作

useEffect(()=>{
    const loadApi = () => {
        setBusy(true);
        fetchAPI().then(
        (results) => {
            setResults(results);
            setErrs([]);
            setBusy(False);
        },
        (err) => {
            setErrs(errs);
            setBusy(False);
        });
        );
    } 
    if (toggle) {
      loadApi();
      setToggle(false)
    }
},[toggle])

const handleOnClick = () => {
    setToggle(true)
}

答案 1 :(得分:0)

我认为您的实现没有任何问题。它应该工作。但是,如果您正在寻找更好的方法,可以考虑使用reducer和useReducer挂钩。

为所有状态定义一个化简器,包括错误,加载和加载状态。在加载状态下,将禁用设置为false。在加载状态下,您将禁用true。在fetchApi函数中,您可以调度各种操作。在调用API之前,请分派加载状态,然后在返回结果后,分配一个包含有效结果的加载状态。然后,您可以在组件中使用带有useReducer钩子的reducer,该钩子将为您提供状态和调度。使用state.disabled禁用按钮。

Helpful SO discussion around useReducer Good article on how to use useReducer for API calls