1

I am creating a website where the user can search for a query and the results are shown.

I created two components: Searchbar and ResultList, both are functional components with hooks.

Searchbar

The user writes a query, which is sent via axios POST request to the backend when the user preses enter. The backend search the relative query and sends the results back via axios GET request. This is working.

ResultList

The ResultList state is initialised with an array called results.

What I would like: I want to set the results array equal to the what it is returned from the GET request in the Searchbar.

Searchbar code

function Searchbar() {

    const [query, setQuery] = useState("");



    function handlePostQuery(query){

        var myParams = {
            data: query
        }

        if (query != "") {
            axios.post('http://localhost:5000/api/query', myParams)
            .then(function(response){
                    var instructions_div = document.getElementsByClassName("instructions")[0];
                    instructions_div.style.display = "none";

                    console.log("Yes, it sends the query in JSON format to Flask");
           //Perform action based on response
            })
            .catch(function(error){
                console.log(error, "Error on AXIOS post");
           //Perform action based on error
        });

      axios.get('http://localhost:5000/api/query')
        .then(function (response) {
          console.log("AXIOS GET")
          console.log(response);

        })
        .catch(function (error) {
          console.log(error);
        });
      } else {
            alert("The search query cannot be empty")
        }
    }

    return(
    <div>
        <SearchBar
            onChange={(event) => setQuery(event)}
            onRequestSearch={() => handlePostQuery(query)}


            style={{
                marginTop: 200,
                marginLeft: 'auto',
                marginRight: 'auto',
                maxWidth: 800,
            }}
        />
      <ResultList /> # I think I should set the new state of Resultlist here but not sure how
</div>
    )
}


export default Searchbar;

ResultList code

function ResultList() {

    const [results, setResults] = useState(["myemptyinitiallist"]);


  if (results[0] !== "myemptyinitiallist") {
        return (
            <div className="resultlist">
            This should appear only if results is different from "myemptyinitiallist"

            </div>
        )
    } else {
        return(
      <h1>This should appear when results is empty</h1>
        )
    }
}


export default ResultList;

IDEALLY I would like NOT to use class components.

Prova12
  • 643
  • 1
  • 7
  • 25
  • 1
    `ResultList` should accept props. It's not responsible for its own state. The state should belong in `Searchbar` – Patrick Roberts Oct 12 '19 at 20:30
  • Also why are you directly interfering with the DOM from handlePostQuery? – jonrsharpe Oct 12 '19 at 20:38
  • So you are suggesting to add `const [results, setResuts]=useState(["myemptyinitiallist"]);` in my `Searchbar`. And to do something `setResults(response)` in my axios GET? – Prova12 Oct 12 '19 at 20:39
  • I tried `axios.get('http://localhost:5000/api/query') .then(response => setResults(["trytry"])) .then(console.log(results))` but `results` has not changed value – Prova12 Oct 12 '19 at 20:59

1 Answers1

1

Since the response is handled from its parent, it should be a prop in the ResultList

Update the code as

function Searchbar() {
    const [query, setQuery] = useState("");
    const [results, setResults] = useState("");
...
    axios.get('http://localhost:5000/api/query')
        .then(function (response) {
          console.log("AXIOS GET")
          console.log(response);
          setResults(response.data); //set the value
        })
...
   <ResultList results={results}/>

in ResultList

function ResultList({results}) { // destructuring props to get results
  //  const [results, setResults] = useState(["myemptyinitiallist"]); passed as props from parent

  if (results && results[0] !== "myemptyinitiallist") { // make sure the results is set before accessing value at [0]
        return (
            <div className="resultlist">
            This should appear only if results is different from "myemptyinitiallist"
            </div>
        )
    } else {
        return(
      <h1>This should appear when results is empty</h1>
        )
    }
}


export default ResultList;
Dhananjai Pai
  • 5,914
  • 1
  • 10
  • 25
  • Thanks, now I understand better. But if i do as you said, the `GET` is executed before the `POST`. I need the other way around otherwise then the user clicks `enter` on the keyboard it returns the wrong errors. – Prova12 Oct 12 '19 at 21:37
  • if you want the POST to wait for GET to finish you should move it to inside the `.then()` of the first GET request or use async/await – Dhananjai Pai Oct 12 '19 at 21:40
  • Thanks. I tried it does not seems to work as intended: https://stackoverflow.com/questions/58365213/the-promise-is-not-executed-first – Prova12 Oct 13 '19 at 16:51