通过React挂钩重用数据

时间:2019-11-23 02:13:59

标签: javascript reactjs typescript react-hooks

我需要使用钩子重用应用程序中的数据,因此我创建了一个名为useData的钩子。

import { useState } from "react";

export default function useData() {
  const [message, setMessage] = useState("");
  const [type, setType] = useState("error");

  return [{ message, type }, { setMessage, setType }];
}

然后我在下面的应用程序中使用钩子。

function App() {
  const [data, action] = useData();

  const handleClick = () => {
    action.setMessage("Hello message");
    action.setType("info");

    alert(JSON.stringify(data));
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button className="btn" onClick={handleClick}>
        Alert Data
      </button>
    </div>
  );
}

当我第一次单击按钮Alert Data时,它将发出警报

{message: "", type: "error"}

我的期望是

{message: "Hello message", type: "info"}

我在这里做错了什么?请让我知道,有什么办法可以解决此代码?

以下是代码和框的代码:https://codesandbox.io/embed/romantic-hugle-zm2e2?fontsize=14&hidenavigation=1&theme=dark

感谢您的关注。

2 个答案:

答案 0 :(得分:1)

您指望data会在您调用onClick处理程序的那一刻被更新,但是直到下一次渲染时才会如此。相反,请考虑使用useEffect挂钩。在下面的示例中,我还创建了一个有状态的open变量来告知模式何时打开。

function App() {
  const [data, action] = useData();
  const [open, setOpen] = useState(false);

  const handleClick = () => {
    action.setMessage("Hello message");
    action.setType("info");
    setOpen(true);
  };

  useEffect(() => {
    if (open) {
      alert(JSON.stringify(data));
      setOpen(false);
    }
  }, [open, data])

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button className="btn" onClick={handleClick}>
        Alert Data
      </button>
    </div>
  );
}

答案 1 :(得分:1)

在React.js中,setState不是同步函数。也就是说,setState不会立即更改状态。对于这种情况,setState具有带有完成回调的版本。您可以使用完成回调定义自定义的挂钩。幸运的是,有一个名为“ use-state-with-callback”的npm软件包。

或者您可以按以下方式编写代码。

useData.js

export default function useData(msg, cb) {
  
  const [message, setMessage] = useState(msg);
  useEffect(() => cb(message), [message]);

  return [message, setMessage];
}

index.js

function App() {
  
  const callback = (msg) => {
    alert(JSON.stringify(msg));
  }
  const [message, setMessage] = useData({
    content: "",
    type: "error"
  }, callback);

  

  const handleClick = () => {
    setMessage({
      content: "Hello message",
      type: "info"
    });
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button className="btn" onClick={handleClick}>
        Alert Data
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

这很好。