我需要使用钩子重用应用程序中的数据,因此我创建了一个名为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
感谢您的关注。
答案 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);
这很好。