user3348410
user3348410

Reputation: 2833

React hooks not set state at first time

i have a problem with hooks.

i'm using react-hooks, i have a button which at onClick getting data from api and setState with it.

Problem is:

when i click to button first time i get response from api but can't set it to state. When click to button second time i can setState. Why it happened ?

here is my component look like:

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;

i tried to using fetchData function like that:

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


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

      }

but it's not helped too

Upvotes: 4

Views: 5816

Answers (4)

krishnan
krishnan

Reputation: 792

@Nicholas Tower has already answered your question. But if you are looking for code

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;

just place log before return (. This should do

Upvotes: 0

Mika
Mika

Reputation: 642

I would not use an effect for it, effects are useful if the props or state changes and can thereby substitute lifecycle methods like componentDidMount, componentDidUpdate, componentWillUnmount, etc.. But in your case these props haven't changed yet (you want to change your state though). Btw, be aware that @Asking's approach will fetch data on EVERY rerender (props or state change). If you want to use useEffect, be sure to add the second parameter to tell React when to update.

Normally, your code should work, I haven't tested but looks legit. Have you used developer tools for react to check if the state/hook has changed? Because if you say it did not work because of the console.log printing: Have in mind that setA() is an async function. The state was most likely not yet changed when you try to print it. If you haven't react developer tools (which I highly recommend) you can check the real state by adding this code in the function:

useEffect(() => console.log(a), [a]);

I have a few real improvements to your code though:

    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;

By adding useCallback you ensure that the function is memorized and not declared again and again on every rerender.

Upvotes: 0

Nicholas Tower
Nicholas Tower

Reputation: 85161

a is a const. It's impossible to change it, so there's no way your console.log statement at the end of fetchData could ever log out something different than the value that a had when fetchData was created.

So that's not what setA does. The point of setA isn't to change the value of the const, but to cause the component to rerender. On that new render, a new set of variables will be created, and the new a will get the new value. Move your console.log out to the body of your component, and you'll see it rerender with the new value.

In short: Your code appears to be already working, you just have the wrong logging.

Upvotes: 4

Asking
Asking

Reputation: 4202

If your scope is to fetch data, use this:

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

Now your response will be stored in data variable.

Upvotes: 0

Related Questions