React挂钩没有在第一时间设置状态

时间:2019-12-15 12:54:01

标签: javascript reactjs

我对钩子有问题。

我正在使用react-hooks,我有一个按钮,它在onClick上从api和setState获取数据。

问题是:

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

这是我的组件外观:

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;

我试图使用像这样的fetchData函数:

 function fetchData() {
        let data = {
            id: 1
        }


        axios.post(baseUrl, data)
        .then(res => {
          if (res.data) {
            setA(res.data)
          }
          console.log(a)
        })

      }

但它也无济于事

4 个答案:

答案 0 :(得分:3)

a是一个常量。无法更改它,因此fetchData末尾的console.log语句无法注销与创建fetchData时a的值不同的内容。

这不是setA所做的。 setA的意义不是要更改const的值,而是要使组件重新呈现。在该新渲染上,将创建一组新的变量,并且新的a将获得新的值。将console.log移出到组件主体,您将看到它以新值重新呈现。

简而言之:您的代码似乎已经可以使用,只是您的日志记录有误。

答案 1 :(得分:0)

如果您要获取数据,请使用以下命令:

const [data, setData] = useState("");
  useEffect(async () => {
    const result = await axios(
      'here will be your api',
    );
    setData(result.data);
  });

现在,您的回复将存储在data变量中。

答案 2 :(得分:0)

我不会为此使用效果,如果道具或状态发生变化,效果会很有用,因此可以替代生命周期方法,例如componentDidMount,componentDidUpdate,componentWillUnmount等。但是在您的情况下,这些道具尚未更改(您想要更改您的状态)。顺便说一句,请注意,@ Asking的方法将在每次重新渲染(属性或状态更改)时获取数据。如果要使用useEffect,请确保添加第二个参数以告知React何时更新。

通常,您的代码应该可以运行,我尚未测试过,但看起来很合法。您是否使用开发人员工具做出反应以检查状态/挂钩是否已更改?因为如果您说它由于console.log打印而无法工作:请记住setA()是一个异步函数。当您尝试打印状态时,状态很可能尚未更改。如果您对开发人员工具没有反应(我强烈建议您使用),则可以通过在函数中添加以下代码来检查真实状态:

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,您可以确保该函数已存储并且在每次重新渲染时都不会一次又一次声明。

答案 3 :(得分:0)

@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;

仅将日志放在return (之前。这应该做