How to keep a value with react context?

Viewed 428

Here are 3 basic components searchBar which refers to the search bar form and, the searchPage component which displays the search results, and of course, the app component which contains them all.

mechanism:

  1. the user submits an input in the searchBar component, the handleSubmit function gets fired, which changes the state of setSearchedProducts to the input value, by useContext AND getting pushed to the ("/SearchPage") by history.push() .

import {useState, useContext } from "react";
import { useHistory } from "react-router-dom";
import { LocaleContext } from "../../../LocaleContext";



const SearchBar = () => {
    const history = useHistory();
    const {setSearchedTerm} = useContext(LocaleContext);

    
    const handleSubmit = (SearchTerm) => {
        setSearchedProducts(SearchTerm)
        history.push("/SearchPage");
    }
    
    
    return (
      <form>
        <input onSubmit={(e) => handleSubmit(e.target.value)}>
        </input>
        <button type="submit">Submit</button>
      </form>
    )
}

export default SearchBar

  1. the value gets sent to the app component by react context and the state gets set to the value while still pushing to the ("/searchPage").

import { useState, useMemo } from "react";
import { searchBar, searchPage } from "./components";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import  {LocaleContext} from "./LocaleContext"


const App = () => {

 const [searchedTerm, setSearchedTerm] = useState("");


 const providerValue = useMemo(() => ({searchedTerm, setSearchedTerm}),
 [searchedTerm, setSearchedTerm])



    return (
        <Router>
            <LocaleContext.Provider value={providerValue}>
            
                <searchBar />
                
                <Switch>
                    <Route exact path="/SearchPage">
                        <SearchPage />
                    </Route>
                </Switch>

            </LocaleContext.Provider>
        </Router>

    );
}

export default (App);

  1. displaying the searchPage component, which gets the state value by using useContext, and with useEffect, the fetchProducts() function gets fired, that fetches a set of products based on the state value.

import {useState, useEffect, useContext}  from 'react';
import { LocaleContext } from "../../LocaleContext";

const SearchPage = ({}) => {

  const [products, setProducts] = useState([]);
  const {searchedTerm} = useContext(LocaleContext);

  const fetchProducts = (term) => {
      setLoading(true);
      const url = new URL(
          "https://example/products"
      );

      let params = {
          "query": term
      };

      Object.keys(params)
          .forEach(key => url.searchParams.append(key, params[key]));

      let headers = {
          "Accept": "application/json",
          "Content-Type": "application/json",
      };

      fetch(url, {
          method: "GET",
          headers: headers,
      })
          .then(response => response.json())
          .then(json => {
              setProducts(json); 
          });

  }



  useEffect(() => {
      fetchProducts(searchedProducts)
  }, [])


  return (
      {
        products.map(product => (
          <div>
            {product.name}
          </div>
        ))
      }
  )
}

export default SearchPage

Issues:

  • when the router changes to the ("/searchPage") component state value get lost, meaning it returns to "" value. ?
  • lesser problem, if the user sends an empty string (" "), and the API needs a value or it will give an error, what is the solution to that?
  • is there a way of keeping the value after reloading the page?

import {createContext} from "react";

export const LocaleContext = createContext(null);

this is the localeContext component if needed.

2 Answers

you have to add e.preventDefault() in your onSubmit handler. Otherwise you're getting a page reload which causes a state loss.

I noticed "setSearchedProducts" & "setSearchedTerm" should be the same in your code below. This might be your issue!

const SearchBar = () => {
    ...
    const {setSearchedTerm} = useContext(LocaleContext);

    
    const handleSubmit = (SearchTerm) => {
        setSearchedProducts(SearchTerm)
        ...
    }

Related