React: отрисовка элемента при валидном значении input

Есть приложение, которое отображает погоду в локации, которую пользователь вписывает в input, каждый раз создавая блок-карточку с названием города, погодными данными и т.д. Все данные берутся из апишки openweathermap.org. Сама логика работает, но не учитываются ошибки, вроде неверно введенной локации. Пробовал несколько способов, но все они мне кажутся костыльными. Как правильнее всего блокировать отрисовку блока при неверно введенном городе и обнулить api после самой отрисовки(чтобы информация не тянулась даже при пустом input)?

App.js

import React, { useEffect, useState } from "react";
import axios from "axios";

import {BsCloudHaze2Fill, BsCloudDrizzleFill, BsEye, BsWater, BsThermometer, BsWind, BsFillThunderboltFill} from 'react-icons/bs'
import {IoSunny, IoRainy, IoCloudy, IoSnow, IoThunderstorm} from 'react-icons/io5'
import {TbTemperatureCelsius, TbMist} from 'react-icons/tb'
import {ImSpinner8} from 'react-icons/im'

import './scss/style.scss';

import Form from "./components/form";
import Weather from "./components/weather";

function App() {
  const [data, setData] = useState(null);
  const [location, setLocation] = useState('Moscow');
  const [error, setError] = useState('');

  const [listItem, setListItem] = useState([])

  useEffect(()=> {
    const apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${location}&units=metric&appid=ff5bb4c4a9717f82bb05d858d81d8eb0&lang=ru`;

    axios.get(apiUrl).then((response) => {
      setData(response.data);
    }).catch(err=>{
      setError(err);
    });
  }, [location]);

  useEffect(()=> {
    const timer = setTimeout(() => {
      setError('');
    }, 2000)
    return () => clearTimeout(timer);
  }, [error])

  if (!data) {
    return <div>
      <div className="flex flex_center spin">
        <ImSpinner8 className="animate-spin"/>
      </div>
    </div>
  }

  let icon;
  switch (data.weather[0].main) {
    case 'Clear':
      icon = <IoSunny className="color-yellow" />
      break
    case 'Clouds':
      icon = <IoCloudy />
      break
    case 'Snow':
      icon = <IoSnow className="color-blue" />
      break
    case 'Rain':
      icon = <IoRainy className="color-blue" />
      break
    case 'Drizzle':
      icon = <BsCloudDrizzleFill className="color-dark-blue" />
      break
    case 'Thunderstorm':
      icon = <IoThunderstorm className="color-dark-blue" />
      break
    case 'Mist':
      icon = <TbMist className="color-gray" />
      break
  }

  const date = new Date();

  return (
    <div className="app">
      <div className="container">
        <Form 
          data={data}
          error={error} 
          listItem={listItem} 
          setListItem={setListItem} 
          setLocation={setLocation}
        />
      </div>
      <div className="container">
        <div className="flex flex_center app_block">
          <Weather listItem={listItem} setListItem={setListItem} />
        </div>
      </div>
    </div>
  );
};

export default App;

Form.jsx

import React, { useState } from "react";
import { v4 as uuidv4 } from 'uuid';
import { IoSearch } from 'react-icons/io5'

function Form({ error, listItem, setListItem, setLocation }) {
  const [inputValue, setInputValue] = useState('');

  const handInput = (e) => {
    setInputValue(e.target.value);
  };

  const handSubmit = (e) => {
    if (inputValue !== '') {
      setLocation(inputValue);
      setListItem(
        [...listItem, {
          id: uuidv4(),
          location: inputValue
        }]
      )
    }
    document.querySelector('input').value = '';
    e.preventDefault();
  };

  return (
    <div>
      <div className="app_error">{error && <div>Ошибка, веденный вами город не найден!</div>}</div>
      <form className="app_form">
        <input onChange={(e)=> handInput(e)} type="text" name="city" className="app_form_input" placeholder="Введите город" />
        <button onClick={(e)=> handSubmit(e)} className="flex app_form_button"><IoSearch /></button>
      </form>
    </div>
  );
}

export default Form;

weather.jsx

import React from "react";
import {TbTemperatureCelsius} from 'react-icons/tb'

function Weather({ error, listItem, setListItem }) {

    function deleteItem(id) {
        let newListItem = [...listItem].filter(listItem => listItem.id !== id);
        setListItem(newListItem);
    }

    return (
        <div>
            {
                listItem.map( item => (
                    <div id={item.id} key={item.id}>
                        <div>{ item.location }</div>
                        <button onClick={() => deleteItem(item.id)}>X</button>
                    </div>
                ))
            }
        </div>
    );
}

export default Weather;

Ответы (0 шт):