【问题标题】:InvalidValueError: not an instance of HTMLInputElement in React projectInvalidValueError:不是 React 项目中 HTMLInputElement 的实例
【发布时间】:2020-10-04 15:26:55
【问题描述】:

我正在尝试在我的 React 项目中添加一个谷歌自动完成功能到我的位置输入,但我收到了这个错误:InvalidValueError: not an instance of HTMLInputElement. 我猜当事件触发时我得到了错误,但我不知道它来自哪里。

这是我的代码

搜索.js

import React, { useState, useContext } from "react";
import DisplaySearchBar from "../layout/DisplaySearchBar";
import RestContext from "../context/restaurant/restContext";
import AlertContext from "../context/alert/alertContext";

const Search = () => {
  const restContext = useContext(RestContext);
  const alertContext = useContext(AlertContext);

  const [where, setWhere] = useState("");
  const [what, setWhat] = useState("");
  const [sortBy, setSortBy] = useState("best_match");
  const [city, setCity] = useState("");

  const sortByOptions = {
    "Best Match": "best_match",
    "Highest Rated": "rating",
    "Most Reviewed": "review_count",
  };

  // give active class to option selected
  const getSortByClass = (sortByOption) => {
    if (sortBy === sortByOption) {
      return "active";
    } else {
      return "";
    }
  };

  // set the state of a sorting option
  const handleSortByChange = (sortByOption) => {
    setSortBy(sortByOption);
  };

  //handle input changes
  const handleChange = (e) => {
    if (e.target.name === "what") {
      setWhat(e.target.value);
    } else if (e.target.name === "where") {
      setWhere(e.target.value);
    }
  };

  const onSubmit = (e) => {
    e.preventDefault();
    if (where && what) {
      restContext.getRestaurants({ where, what, sortBy });

      setWhere("");
      setWhat("");
      setSortBy("best_match");
    } else {
      alertContext.setAlert("Please insert somethiing", "error");
    }
  };

  // displays sort options
  const renderSortByOptions = () => {
    return Object.keys(sortByOptions).map((sortByOption) => {
      let sortByOptionValue = sortByOptions[sortByOption];
      return (
        <li
          className={getSortByClass(sortByOptionValue)}
          key={sortByOptionValue}
          onClick={() => handleSortByChange(sortByOptionValue)}
        >
          {sortByOption}
        </li>
      );
    });
  };

  // google suggestion

  const handleScriptLoad = () => {
    const handlePlaceSelect = () => {
      // Extract City From Address Object

      const addressObject = autocomplete.getPlace();
      const address = addressObject.address_components;

      // Check if address is valid
      if (address) {
        // Set State
        setCity(address[0].long_name);
      }
    };

    const options = {
      types: ["(cities)"],
    }; // To disable any eslint 'google not defined' errors

    // Initialize Google Autocomplete
    /*global google*/ let autocomplete = new google.maps.places.Autocomplete(
      document.getElementById("autocomplete"),
      options
    );

    // address.
    autocomplete.setFields(["address_components", "formatted_address"]);

    // Fire Event when a suggested name is selected
    autocomplete.addListener("place_changed", handlePlaceSelect);
  };

  return (
    <DisplaySearchBar
      onSubmit={onSubmit}
      handleChange={handleChange}
      renderSortByOptions={renderSortByOptions}
      where={where}
      what={what}
      handleScriptLoad={handleScriptLoad}
    />
  );
};

export default Search;

DisplaySearch.js

import React, { useContext } from "react";
import PropTypes from "prop-types";
import RestContext from "../context/restaurant/restContext";
//Import React Script Libraray to load Google object
import Script from "react-load-script";

const DisplaySearchBar = ({
  renderSortByOptions,
  onSubmit,
  where,
  handleChange,
  what,
  handleScriptLoad,
}) => {
  const restContext = useContext(RestContext);

  const { restaurants, clearSearch } = restContext;

  const googleUrl = `https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_API_KEY}&libraries=places`;

  return (
    <div className="searchBar">
      <h1>Where are you going to eat tonigth?</h1>

      <div className="searchBar-sort-options">
        <ul>{renderSortByOptions()}</ul>
      </div>

      <form onSubmit={onSubmit} className="searchBar-form">
        <div className="searchBar-input">
          <Script url={googleUrl} onLoad={handleScriptLoad} />
          <input
            type="text"
            name="where"
            placeholder="Where do you want to eat?"
            value={where}
            onChange={handleChange}
          />

          <input
            type="text"
            name="what"
            placeholder="What do you want to eat?"
            onChange={handleChange}
            value={what}
          />
        </div>

        <div className="searchBar-submit">
          <input
            className="myButton button"
            type="submit"
            name="submit"
            value="Search"
          ></input>

          {restaurants.length > 0 && (
            <button className="clearButton button" onClick={clearSearch}>
              Clear
            </button>
          )}
        </div>
      </form>
    </div>
  );
};

DisplaySearchBar.propTypes = {
  renderSortByOptions: PropTypes.func.isRequired,
  where: PropTypes.string.isRequired,
  handleChange: PropTypes.func.isRequired,
  what: PropTypes.string.isRequired,
  handleScriptLoad: PropTypes.func.isRequired,
};

export default DisplaySearchBar;

感谢您的帮助

【问题讨论】:

    标签: javascript reactjs autocomplete googleplacesautocomplete


    【解决方案1】:

    我发现了问题。 我没有为我的输入提供 ID“自动完成”,因此当事件触发时它无法到达它。

    【讨论】:

      【解决方案2】:

      您的代码非常复杂。您可能可以使用其中一个 npm 包节省一些行并使您的组件更精简。我建议你给https://github.com/hibiken/react-places-autocomplete 一个机会。

      为了提高性能,还可以考虑在功能组件 https://reactjs.org/docs/hooks-reference.html#usememo 中使用 React 的 useMemouseCallback

      【讨论】:

        猜你喜欢
        • 2016-03-07
        • 1970-01-01
        • 2017-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-02
        • 2019-07-17
        • 1970-01-01
        相关资源
        最近更新 更多