Javascript 第一次未设置状态

Javascript 第一次未设置状态,javascript,reactjs,Javascript,Reactjs,我有一个钩子的问题 我使用的是react钩子,我有一个按钮,可以点击从api获取数据并设置状态 问题是: 当我第一次单击按钮时,我从api获得响应,但无法将其设置为状态。第二次单击按钮时,我可以设置状态。为什么会这样 下面是我的组件的外观: function App() { const [a, setA] = useState(null); const fetchData = () => { let data = { id: 1 }

我有一个钩子的问题

我使用的是react钩子,我有一个按钮,可以点击从api获取数据并设置状态

问题是:

当我第一次单击按钮时,我从api获得响应,但无法将其设置为状态。第二次单击按钮时,我可以设置状态。为什么会这样

下面是我的组件的外观:

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