1

I didn't get data for the first time.

Here is my screen shot when I search for the first time it return undefined and when I search for second time it return proper data. enter image description here

How to I fix this problem. And please also explain what does it happens. I search this behavior from 2 days but I didn't find any solution even from stack overflow. Here is my code.

import logo from './logo.svg';
import './App.css';
import Navbar from './components/Navbar';
import { useEffect, useMemo, useState } from 'react'
function App() {
  const [searchWord, setSearchWord] = useState('');
  const [responseWord, setResponseWord] = useState();
  const [isLoad, setIsLoad] = useState(false)
  const [urlLink, setUrlLink] = useState('')
  async function fetchWord(word) {
    console.log(isLoad)
    const res = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${word}`);
    const data = await res.json();
    setIsLoad(true)
    setResponseWord(data)
    console.log(responseWord)
    console.log(isLoad)
  }

  return (
    <>
      <Navbar />
      <div className="container mt-4">
        <div className="row">
          <div className="column bg-success text-light text-center col-3" style={{ height: "100vh" }}>
            <h4> English Dictionary</h4>
          </div>
          <div className="column col-5 bg-light">
            {
              isLoad &&
              <>
                <h3 className='word'>{responseWord.word}</h3>
              </>
            }
          </div>
          <div className="row col-3" style={{ height: 50 }}>
            <form className="d-flex" role="search" onSubmit={(e) => e.preventDefault()}>
              <input className="form-control mr-sm-2" placeholder="Search"
                onChange={(e) => setSearchWord(e.target.value)}
                value={searchWord}
              />
              <button className="btn btn-outline-success my-2 my-sm-0" type="submit" onClick={() => fetchWord(searchWord)} >Search</button>
            </form>
          </div>

        </div>

      </div>
    </>
  );
}

export default App;

Phil
  • 157,677
  • 23
  • 242
  • 245
  • Does this answer your question? [The useState set method is not reflecting a change immediately](https://stackoverflow.com/questions/54069253/the-usestate-set-method-is-not-reflecting-a-change-immediately) – Phil Sep 07 '22 at 01:55
  • Stop relying on `console.log()` to verify state – Phil Sep 07 '22 at 01:56

3 Answers3

0

When responseWord was printed the first time, responseWord's value was not updated to new value. Because setState operates asynchronously.

Use useEffect hook instead.

async function fetchWord(word) {
  console.log(isLoad)
  const res = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${word}`);
  const data = await res.json();
  setIsLoad(true)
  setResponseWord(data)
}

useEffect(() => {
  console.log(responseWord);
}, [responseWord]);
ChanHyeok-Im
  • 541
  • 3
  • 11
0

can you try this one please i think will it help you out

    import React, { useEffect, useMemo, useState } from "react";
const App=()=> {
  const [searchWord, setSearchWord] = useState("");
  const [responseWord, setResponseWord] = useState([]);
  const [isLoad, setIsLoad] = useState(false);
  const [urlLink, setUrlLink] = useState("");
  const fetchWord = async (word) => {
    console.log(word);
    try {
      setIsLoad(false);
      const res = await fetch(
        `https://api.dictionaryapi.dev/api/v2/entries/en/${word}`
      );
      const data = await res.json();
      setIsLoad(true);
      setResponseWord(data);
    } catch (er) {
      setIsLoad(false);
    }
  };
  const HandleSubmit = (e) => {
    e.preventDefault();
    fetchWord(searchWord);
  };

  return (
    <>
       <Navbar /> 
      <div className="container mt-4">
        <div className="row">
          <div
            className="column bg-success text-light text-center col-3"
            style={{ height: "100vh" }}
          >
            <h4> English Dictionary</h4>
          </div>
          <div className="column col-5 bg-light">
            {isLoad && responseWord.length !== 0 && (
              <>
                {/* <h3 className="word">{responseWord.word}</h3> */}
                {responseWord.map((eg, i) => (
                  <h3 key={i || eg}>{eg.word}</h3>
                ))}
              </>
            )}
          </div>
          <div className="row col-3" style={{ height: 50 }}>
            <form className="d-flex" role="search" onSubmit={HandleSubmit}>
              <input
                className="form-control mr-sm-2"
                placeholder="Search"
                onChange={(e) => setSearchWord(e.target.value)}
                value={searchWord}
              />
              <button
                className="btn btn-outline-success my-2 my-sm-0"
                type="submit"
              >
                Search
              </button>
            </form>
          </div>
        </div>
      </div>
    </>
  );
}
export default App;

don't console inside the Asynce function cause async function will await until responce came so your results will be previous state and assign your useState intially with empty array that will work properly if in case empty data

jsBug
  • 348
  • 1
  • 9
0

Muhammad, you're off to a great start here. First, let's take a look at your code as it is at the moment. Then, I'll make a couple of recommendations on how to refactor your code.

Congrats! You're actually getting data the first time you click the button and trigger fetchWord function.

You're just calling console.log(responseWord) and console.log(isLoad) too early. You're trying to log responseWord and isLoad right after updating their state within the same function. This happens because "calls to setState are asynchronous inside event handlers" and changes to state variables do NOT reflect the new value immediately after calling setState.

"When state changes, the component responds by re-rendering." And it is in the new re-render that the new state value will be reflected.

Why doesn’t React update state synchronously? According to React documentation, React intentionally “waits” until all components call setState() in their event handlers before starting to re-render. This boosts performance by avoiding unnecessary re-renders.

When you call setResponseWord("new value") and setIsLoad("new value"), and then try to log the new state values to the console before React re-denders your component, you get false and undefined.

Try console.log(data) instead of console.log(responseWord).

Since you have access to const data = await res.json(); inside your function and before the component re-render happens, you should be able to see your data right away.

The images below ilustrate this example (focus on line 16): fetchWord function

console.log(data)

Next, recommendations:

1 . It is recommended to make your AJAX call to an API using useEffect Hook. This way, you can add the serachWord to the dependency array, and useEffect will execute every time the value of seachWord changes.

In your case, you make your fetch call on button click, but if, for example, you created a web app in which you needed the data to be populated right away without the user having to click a button, useEffect Hook will shine at its best because useEffect automatically runs the side-effect right after initial rendering, and on later renderings only if the value of the variables you passed in the dependency array change.

See the image below from the React documentation to get an idea of how you could refactor your code: enter image description here

  1. Another recommendation is to get rid of the onClick property in the button, and just let the handleSubmit function call fetchWord (see lines 38 and 21-24). enter image description here

This information should help you move your app forward. And you're doing great. I see that you're successfully updating state variables, using async/await, making AJAX calls using fetch() and learning React.

Please take a look at the reference list below:

https://reactjs.org/docs/faq-state.html

https://reactjs.org/docs/faq-ajax.html

https://reactjs.org/docs/forms.html

Lu0.atx
  • 11
  • 2