skip to Main Content

I have been trying to make a dictionary app for a challenge I saw online and it is my first attemp on using fetch api. I think I am failing to understand a core concept which gets me stuck here.

First of all, I created a useFetch hook to get all the data for the term that is searched as follows:

try {
    nProgress.start();

    const res = await fetch(url);
    if (!res.ok) throw new Error(res.status);
    const data = await res.json();

    dataSetter(data);
    errorSetter(false);
  } catch (err) {
    errorSetter(true);
  } finally {
    loadingSetter(false);
    nProgress.done();
  }

And then in my App component I created an async function to use the hook along with my states:

async function fetchData(input) {
    useFetch(
      `https://api.dictionaryapi.dev/api/v2/entries/en/${input}`,
      (data) => {
        setTerm(data[0]);
      },
      setLoading,
      setIsError
    );
  }

This is how my Word component is rendered inside the App component:

{!loading && !isError && <Word data={term} darkTheme={darkTheme} />}

The word component has a child component called Definitions which I pass the data as is, however when I try to map over the data that (?) should’ve been fetched by now before the rendering happened, since I am already checking if the data is fully loaded before I even render the parent component which renders without any problems, I am receiving an error caused by data being null on Definitions component.

To provide more details here’s how my mapping looks like:

{data.meanings.map((meaning) => {
              /* bunch of jsx here */
              {meaning.definitions.map((definition) => {
                <li className="marker:text-purple-600 pt-4">
                  {definition.definition}
                </li>;
              })}
        </div>;
      })}

———— Edit ————

console error

Here’s my form element where I get my input.

<form className="w-full h-full" onSubmit={handleSubmit}>
        <input
          type="search"
          placeholder="Search for word"
          value={input}
          onChange={handleChange}
        />
</form>

And this is how I handle input

const [queryParams, setQueryParams] = useSearchParams();
  const initialInput = queryParams.get("term") ?? "hello";

  const [input, setInput] = useState("");
  const [isValid, setIsValid] = useState(true);

  useEffect(() => {
    setInput(initialInput);
    fetchData(initialInput);
  }, [initialInput]);

  const handleChange = (e) => {
    setInput(e.target.value);
  };

  const handleSubmit = (e) => {
    e.preventDefault();

    if (input.length < 1) {
      setIsValid(false);
      return;
    }

    setIsValid(true);
    setQueryParams({ term: input });
  };

2

Answers


  1. Chosen as BEST ANSWER

    Ok, I found the answer myself and posting here for future searches.

    I only had to make a fallback "component" or just render nothing when data is not fetched yet on Definitions component.

    if (!data) {
      return null; // Return null or a loading/error message when data is null
    }
    

  2. Please note that mapping is still a function that should return something. Add a return statement before the JSX element in the inner mapping function.

     {data.meanings.map((meaning) => {
      return ( // Add this line
        <div>
          {/* bunch of jsx here */}
          {meaning.definitions.map((definition) => {
            return (
              <li className="marker:text-purple-600 pt-4">
                {definition.definition}
              </li>
            );
          })}
        </div>
      );
    })}
    

    Furthermore, if you want to check the rendered output, you can use console.log.

    async function fetchData(input) {
        useFetch(
          `https://api.dictionaryapi.dev/api/v2/entries/en/${input}`,
          (data) => {
            console.log("Starting useFetch") // Add this line
            setTerm(data[0]);
          },
          setLoading,
          setIsError
        );
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search