Javascript 第一次未设置状态
我有一个钩子的问题 我使用的是react钩子,我有一个按钮,可以点击从api获取数据并设置状态 问题是: 当我第一次单击按钮时,我从api获得响应,但无法将其设置为状态。第二次单击按钮时,我可以设置状态。为什么会这样 下面是我的组件的外观:Javascript 第一次未设置状态,javascript,reactjs,Javascript,Reactjs,我有一个钩子的问题 我使用的是react钩子,我有一个按钮,可以点击从api获取数据并设置状态 问题是: 当我第一次单击按钮时,我从api获得响应,但无法将其设置为状态。第二次单击按钮时,我可以设置状态。为什么会这样 下面是我的组件的外观: function App() { const [a, setA] = useState(null); const fetchData = () => { let data = { id: 1 }
function App() {
const [a, setA] = useState(null);
const fetchData = () => {
let data = {
id: 1
}
axios.post(baseUrl, data)
.then(res => {
if (res.data) {
setA(res.data)
}
console.log(a)
})
}
return (
<div className="App">
<div>
<button onClick={fetchData}></button>
</div>
</div>
);
}
export default App;
但这也没有帮助如果您的工作范围是获取数据,请使用以下方法: const[data,setData]=useState; useEffectasync=>{ 常量结果=等待axios “这将是您的api”, ; setDataresult.data;
}; 如果您的范围是获取数据,请使用以下方法: const[data,setData]=useState; useEffectasync=>{ 常量结果=等待axios “这将是您的api”, ; setDataresult.data; }; a是常数。无法更改它,因此fetchData末尾的console.log语句无法注销与创建fetchData时的值不同的内容 所以setA不是这么做的。setA的作用不是改变常量的值,而是使组件重新运行。在新渲染上,将创建一组新的变量,新的a将获得新值。将您的console.log移出到组件主体,您将看到它使用新值重新加载 简而言之:您的代码似乎已经在运行,只是日志记录错误。a是常量。无法更改它,因此fetchData末尾的console.log语句无法注销与创建fetchData时的值不同的内容 所以setA不是这么做的。setA的作用不是改变常量的值,而是使组件重新运行。在新渲染上,将创建一组新的变量,新的a将获得新值。将您的console.log移出到组件主体,您将看到它使用新值重新加载
简而言之:您的代码似乎已经在运行,只是日志记录错误。我不会对其使用效果,如果道具或状态发生更改,效果会很有用,因此可以替代生命周期方法,如componentDidMount、componentDidUpdate、componentWillUnmount等。。但是在你的情况下,这些道具还没有改变,但是你想改变你的状态。顺便说一句,请注意@Asking的方法将获取每次重播道具或状态更改的数据。如果要使用useEffect,请确保添加第二个参数,以告知React何时更新 通常情况下,您的代码应该可以工作,我还没有测试过,但看起来是合法的。您是否使用开发人员工具来检查状态/挂钩是否已更改?因为如果您说它因为console.log打印而无法工作:请记住setA是一个异步函数。当您尝试打印时,状态很可能尚未更改。如果您尚未使用我极力推荐的react developer工具,您可以通过在函数中添加以下代码来检查真实状态:
useEffect(() => console.log(a), [a]);
不过,我对您的代码有一些真正的改进:
function App() {
const [a, setA] = useState(null);
const fetchData = useCallback(async () => {
let data = {
id: 1
}
const res = await axios.post(baseUrl, data);
setA(res.data);
}, []);
return (
<div className="App">
<div>
<button onClick={fetchData}></button>
</div>
</div>
);
}
export default App;
通过添加useCallback,您可以确保在每次重新加载时都能记住函数,而不是一次又一次地声明函数。我不会对它使用效果,如果道具或状态发生变化,效果会很有用,因此可以替代生命周期方法,如componentDidMount、componentDidUpdate、componentWillUnmount等。。但是在你的情况下,这些道具还没有改变,但是你想改变你的状态。顺便说一句,请注意@Asking的方法将获取每次重播道具或状态更改的数据。如果要使用useEffect,请确保添加第二个参数,以告知React何时更新 通常情况下,您的代码应该可以工作,我还没有测试过,但看起来是合法的。您是否使用开发人员工具来检查状态/挂钩是否已更改?因为如果您说它因为console.log打印而无法工作:请记住setA是一个异步函数。当您尝试打印时,状态很可能尚未更改。如果您尚未使用我极力推荐的react developer工具,您可以通过在函数中添加以下代码来检查真实状态:
useEffect(() => console.log(a), [a]);
不过,我对您的代码有一些真正的改进:
function App() {
const [a, setA] = useState(null);
const fetchData = useCallback(async () => {
let data = {
id: 1
}
const res = await axios.post(baseUrl, data);
setA(res.data);
}, []);
return (
<div className="App">
<div>
<button onClick={fetchData}></button>
</div>
</div>
);
}
export default App;
通过添加useCallback,您可以确保函数被记忆,而不是在每次重新加载时一次又一次地声明。@Nicholas Tower已经回答了您的问题。但是如果你正在寻找代码
function App() {
const [a, setA] = useState(null);
const fetchData = () => {
let data = {
id: 1
}
axios.post(baseUrl, data)
.then(res => {
if (res.data) {
setA(res.data)
}
})
}
console.log(a)
return (
<div className="App">
<div>
<button onClick={fetchData}></button>
</div>
</div>
);
}
export default App;
只需在返回前放置日志。这应该可以@Nicholas Tower已经回答了你的问题。但是如果你正在寻找代码
function App() {
const [a, setA] = useState(null);
const fetchData = () => {
let data = {
id: 1
}
axios.post(baseUrl, data)
.then(res => {
if (res.data) {
setA(res.data)
}
})
}
console.log(a)
return (
<div className="App">
<div>
<button onClick={fetchData}></button>
</div>
</div>
);
}
export default App;
只需在返回前放置日志。这应该可以@user3348410,您应该使用useEfect hook进行抓取,因为您使用的是异步调用。@AskingsetA不会在该范围内更改a,但抓取会在第一次工作。@AtulKumar这是第一次,不是。Axios没有json异步方法。你能给我举一些例子说明我的情况吗?
useEffect就像组件一样,不是吗?我不想在componentDidmount中获取数据,当用户单击button@user3348410,您应该使用UseFect钩子进行抓取,因为您使用的是异步调用。@AskingsetA不会在该范围内更改a,但抓取第一次就可以工作。@AtulKumar这是问题所在,不是。Axios没有json异步方法。你能给我举一些例子说明我的情况吗?useEffect就像组件一样,不是吗?我不想在componentDidmount中获取数据,当用户单击按钮时我不想获取数据。我想在componentDidmount上有效,不是吗?我不想一次就成功。ClickUseEffect会在组件上成功。我想不会吧?我不想它马上就开始工作。对不起,它什么也没变。对不起,它成功了!!!非常感谢您抽出时间让我为每个api请求使用useCallBack,对吗?实际上您不需要useCallBack,它只是一种性能改进和最佳实践。使用useCallback时,需要声明依赖参数,因此如果参数发生更改,函数将重新声明。很抱歉,但它没有改变任何事情。对不起,它成功了!!!非常感谢您抽出时间让我为每个api请求使用useCallBack,对吗?实际上您不需要useCallBack,它只是一种性能改进和最佳实践。使用useCallback时,需要声明依赖参数,因此如果参数发生更改,函数将重新声明。看,实际上我理解了我的entrie代码可以很好地工作的一些东西,但是当我返回条件时,比如{a.length?{a}:null}。它不起作用。在得到a的长度之前。您应该检查a是否像这样为空{a&&{a}}。如果你使用你的代码{a.length?{a}:null},你会得到错误,因为a是第一次为null,你试图得到null的长度,这将抛出error,我看到了它,我设置的第一个状态像const[a,setA]=useState[];但这个案子不太管用。这里我有长度,很抱歉我犯了错误,我把它写成const[a,setA]=useStatenull;我的条件是{a!=null{a}}。那就很好了。[a,setA]=useState[]不起作用的原因是a.length解析为0,而0在条件中实际上为false。事实上,我理解我的entrie代码可以很好地解决的一些问题,但当我返回类似于{a.length?{a}:null}的条件时。它不起作用。在得到a的长度之前。您应该检查a是否像这样为空{a&&{a}}。如果你使用你的代码{a.length?{a}:null},你会得到错误,因为a是第一次为null,你试图得到null的长度,这将抛出error,我看到了它,我设置的第一个状态像const[a,setA]=useState[];但这个案子不太管用。这里我有长度,很抱歉我犯了错误,我把它写成const[a,setA]=useStatenull;我的条件是{a!=null{a}}。那就很好了。[a,setA]=useState[]不起作用的原因是a.length解析为0,而0在条件内实际上为false