Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
214 views
in Technique[技术] by (71.8m points)

reactjs - React App crashes when fetching searchresults from django API

My React App is crashing when fetching searchResults from API, I have checked the API urls wise search queries and it works perfectly however when i try to send input via React and display results it crashes and even freezes my PC. I dont understand whats going on here. I have fetched results from the API in React without search query and it works. So the API works when used via Curl and React app can fetch and display all the data but unable to display specific data. Below is my code:

function Search() {
  const [data, setData] = React.useState([]);
  const [searchTerm, setSearchTerm] = React.useState("");
  const handleChange = e => {
    setSearchTerm(e.target.value);
  };
  React.useEffect(() => {
    if (searchTerm) {
      getData(searchTerm);
    }
  });
  const getData = (searchTerm) => {
    axios.get("http://localhost:8000/SearchPost/?search="+searchTerm)
         .then(res => (setData(res.data)))
  }
  return (
    <div className="App">
      <input
        type="text"
        placeholder="Search"
        value={searchTerm}
        onChange={handleChange}
      />
      <ul>
        {data.map(item => (
          <li>{item.co_N}</li>
        ))}
      </ul>
    </div>
  );
}
export default Search;
question from:https://stackoverflow.com/questions/66047561/react-app-crashes-when-fetching-searchresults-from-django-api

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

One solution is to "debounce" setting searchTerm to minimize the request to the API:
we're going to use lodash package particularly it's debounce method (doc here), and useCallback from Hooks API (doc here) :

import React, { useState, useCallback, useRef } from "react";
import _ from "lodash";
import axios from "axios";

import TextField from "@material-ui/core/TextField";

const SearchInputComponent = ({ label }) => {
  const [value, setValue] = useState("");
  const [data, setData] = useState([]);

  const inputRef = useRef(null);

  const debounceLoadData = useCallback(
    _.debounce((value) => {
      getData(value);
    }, 500), // you can set a higher value if you want
    []
  );

  const getData = (name) => {
    axios.get(`https://restcountries.eu/rest/v2/name/${name}`).then((res) => {
      console.log(res);
      setData(res.data);
    });
  };
  const handleSearchFieldChange = (event) => {
    const { value } = event.target;

    setValue(value);
    debounceLoadData(value);
  };

  return (
    <>
      <TextField
        inputRef={inputRef}
        id="searchField"
        value={value}
        label={"search"}
        onChange={handleSearchFieldChange}
      />
      {data &&
<ul>
{data.map(country=>  (
<li key={country.alpha3Code}>{country.name}</li>
))

}

</ul>
}
    </>
  );
};

export default SearchInputComponent;

with this code the front end will wait 500 ms before fetching api with the search input value.

here a sandBox example.

Possible Feature: Make search field generic

If in the future you will need a search component you can make it generic with Context:
first create a context file named for example SearchInputContext.js and add:
SearchInputContext.js

import React, {
  createContext,
  useState
} from 'react';

export const SearchInputContext = createContext({});

export const SearchInputContextProvider = ({ children }) => {
  const [value, setValue] = useState('');

  return (
    <SearchInputContext.Provider
      value={{ searchValue: value, setSearchValue: setValue }}
    >
      {children}
    </SearchInputContext.Provider>
  );
};

Next create a generic searchField component named for example SearchInput.js and add in it :
SearchInput.js

import React, {
  useState,
  useCallback,
  useRef,
  useContext
} from 'react';
import  _ from 'lodash';
import TextField from "@material-ui/core/TextField";
import { SearchInputContext } from './SearchInputContext';

const SearchInputComponent  = () => {
  const [value, setValue] = useState('');
  const { setSearchValue } = useContext(SearchInputContext);
 
  const inputRef = useRef(null);

  const debounceLoadData = useCallback(
    _.debounce((value) => {
      setSearchValue(value);
    }, 500),
    []
  );

  const handleSearchFieldChange = (event) => {
    const { value } = event.target;

    setValue(value);
    debounceLoadData(value);
  };

  return (
    <>
     <TextField
        inputRef={inputRef}
        id="searchField"
        value={value}
        label={"search"}
        onChange={handleSearchFieldChange}
      />
     
    </>
  );
};

export default SearchInputComponent;

After in your App.js (or other component page where you want a searchField) add your ContextProvider like this:
App.js

import {ListPage} from "./searchPage";
import  {SearchInputContextProvider}  from './SearchInputContext';
import "./styles.css";

export default function App() {
  return (
   
<SearchInputContextProvider>
   <ListPage/>
    </SearchInputContextProvider>
   
  );
}

And finally add your searchComponent where you need a search feature like in the ListPage component :
SearchPage.js:

import React, { useState,useContext, useEffect } from "react";
import axios from "axios";
import SearchInputComponent from './SearchInput';
import {SearchInputContext} from './SearchInputContext'


export const ListPage = () => {
 
  const [data, setData] = useState([]);
  const { searchValue } = useContext(SearchInputContext);
 
useEffect(() => {
if(searchValue){
  const getData = (name) => {
    axios.get(`https://restcountries.eu/rest/v2/name/${name}`).then((res) => {
      console.log(res);
      setData(res.data);
    });
  };
 return getData(searchValue)

}
  
}, [ searchValue]);
 
  return (
    <>
     <SearchInputComponent  />
      {data &&
<ul>
{data.map(country=>  (
<li key={country.alpha3Code}>{country.name}</li>
))

}

</ul>
}
    </>
  );
};

here a sandbox link of this example


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...