简体   繁体   中英

How do I fetch search results from multiple API using reactjs

I am new to ReactJS and I am trying to create a search feature with react by fetching data from multiple API. Below is the Search.js file. I tried so many times to make it functions and make the results appear live while typing. I however keep on getting this error message TypeError: values.map is not a function . Where am I going wrong and how do I fix it?

 function Search() { const [input, setInput] = useState(""); const [results, setResults] = useState([]); const urls = [ 'https://jsonplaceholder.typicode.com/posts/1/comments', 'https://jsonplaceholder.typicode.com/comments?postId=1' ] Promise.all(urls.map(url => fetch(url).then((values) => Promise.all(values.map(value => value.json()))).then((response) => response.json()).then((data) => setResults(data)).catch(error => console.log('There was a problem,', error)) ). []) const handleChange = (e) => { e;preventDefault(). setInput(e.target;value). } if (input.length > 0) { results.filter((i) => { return i.name.toLowerCase();match(input). }) } return ( < div className = "search" htmlFor = "search-input" > < input type = "text" name = "query" value = { input } id = "search" placeholder = "Search" onChange = { handleChange } /> { results,map((result. index) => { return ( < div className = "results" key = { index } > < h2 > { result.name } < /h2> < p > { result.body } < /p> { result } < /div> ) }) } </div> ) }
 .search { position: relative; left: 12.78%; right: 26.67%; top: 3%; bottom: 92.97%; }.search input { /* position: absolute; */ width: 40%; height: 43px; right: 384px; margin-top: 50px; top: 1.56%; bottom: 92.97%; background: rgba(0, 31, 51, 0.02); border: 1px solid black; border-radius: 50px; float: left; outline: none; font-family: 'Montserrat', sans-serif; font-style: normal; font-weight: normal; font-size: 16px; line-height: 20px; /* identical to box height */ display: flex; align-items: center; /* Dark */ color: #001F33; } /* Search Icon */ input#search { background-repeat: no-repeat; text-indent: 50px; background-size: 18px; background-position: 30px 15px; } input#search:focus { background-image: none; text-indent: 0px }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Issue

  1. The response you get from fetch(url) is just the one single response, so there's nothing to map.
  2. The data fetching occurs in the function body of the component, so when working this causes render looping since each render cycle fetches data and updates state.
  3. The input.length > 0 filtering before the return does nothing since the returned filtered array isn't saved, and it also incorrectly searches for sub-strings.
  4. Attempt to render result object in the render function, objects are invalid JSX

Solution

  1. Skip the .then((values) => Promise.all(values.map((value) => value.json()))) step and just move on to accessing the JSON data.
  2. Move the data fetching into a mounting useEffect hook so it's run only once.
  3. Move the filter function inline in the render function and use string.prototype.includes to search.
  4. Based on other properties rendered and what is left on the result object I'll assume you probably wanted to render the email property.

Code:

function Search() {
  const [input, setInput] = useState("");
  const [results, setResults] = useState([]);

  useEffect(() => {
    const urls = [
      "https://jsonplaceholder.typicode.com/posts/1/comments",
      "https://jsonplaceholder.typicode.com/comments?postId=1"
    ];

    Promise.all(
      urls.map((url) =>
        fetch(url)
          .then((response) => response.json())
          .then((data) => setResults(data))
          .catch((error) => console.log("There was a problem!", error))
      ),
      []
    );
  }, []);

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

  return (
    <div className="search" htmlFor="search-input">
      <input
        type="text"
        name="query"
        value={input}
        id="search"
        placeholder="Search"
        onChange={handleChange}
      />
      {results
        .filter((i) => i.name.toLowerCase().includes(input))
        .map((result, index) => {
          return (
            <div className="results" key={index}>
              <h2>{result.name}</h2>
              <p>{result.body}</p>
              {result.email}
            </div>
          );
        })}
    </div>
  );
}

编辑 how-do-i-fetch-search-results-from-multiple-api-using-reactjs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM