0

I am pretty new to React.

Previously the search functionality and the productsPage code lived in one file and search worked as expected.

Now I want to decouple the search functionality from productsPage.

This is products.js file where I need items to be searched.

function ProductsPage() {
  var categories = data.categories;
  const [search, setSearch] = useState(null);

  return (
    <>
      <Container fluid id="searchBar">
        <SearchForm searchValue={search} />
      </Container>
      <Container fluid id="productPage">
        <h2 className="text-center py-5">Our Products</h2>
        <CardColumns className="pt-3 mb-5">
          {categories.map((catNames) => (
            <Fragment key={uuid()}>
              {catNames.sub_categories.map((subCat) => (
                <Fragment key={uuid()}>
                  {subCat.items
                    .filter((item) => {
                      if (search == null) return item;
                      else if (
                        item.itemName
                          .toLowerCase()
                          .includes(search.toLowerCase())
                      ) {
                        return item;
                      }
                    })
                    .map((item) => {
                      return (
                        <Card className="mb-4 p-3" key={uuid()}>
                          <div className="prodBorder">
                            <Card.Title className="pt-5 pb-4 text-center">
                              {item.itemName}
                            </Card.Title>
                            <Card.Img
                              src={`${item.image.url}`}
                              className="d-block w-50 mx-auto my-3"
                            />
                            <Card.Subtitle className="pb-4 text-center text-muted">
                              {item.itemDesc}
                            </Card.Subtitle>
                          </div>
                        </Card>
                      );
                    })}
                </Fragment>
              ))}
            </Fragment>
          ))}
        </CardColumns>
      </Container>
    </>
  );
}

export default ProductsPage;

This one is search.js file where the onChange handler lives

function SearchForm(props) {
  const [search, setSearch] = useState(null);

  const searchSpace = (event) => {
    let search = event.target.value;
    setSearch(search);
  };

  return (
    <Form inline className="position-relative mt-4 mx-auto w-75">
      <FontAwesomeIcon icon={faSearch} className="productsSearchIcon" />
      <FormControl
        id="searchfield"
        type="text"
        placeholder="Search products..."
        onChange={(e) => searchSpace(e)}
        className="ml-0 ml-md-3 w-100"
      />
    </Form>
  );
}

export default SearchForm;
invinciblemuffi
  • 908
  • 1
  • 11
  • 22

2 Answers2

2

There are two ways you could do this. You could use state lifting.

Docs: https://reactjs.org/docs/lifting-state-up.html

I've made this example to show how that works:

https://codesandbox.io/s/stupefied-noether-rb1yi?file=/src/App.js

If your app is not small or is going to grow you are better using some sort of global state management such as redux or react context API

Docs: https://redux.js.org/tutorials/essentials/part-1-overview-concepts Docs: https://reactjs.org/docs/context.html

I have made this example using the react context api to give you an idea of how global state management works.

https://codesandbox.io/s/confident-satoshi-upo4c?file=/src/App.js

You will see in this example you can pass data to nested components without the need to pass data through props. When your app grows in size this will make your code a lot cleaner, more efficient and less prone to error. Redux is an alternative (earlier and more popular solution) for global state management.

As a beginner you should try to understand the concepts of state lifting before global state management.

However, if your app is big with nested components, a global state management approach would be the preferred final solution.

Jazz
  • 341
  • 1
  • 6
  • Thank you for the reply. As mentioned in the question being a beginner in react, it's very daunting to go through docs and try to map it to existing code that we work on, it does not always work out that way. Sometimes a small example with a little bit of explanation works way better than the actual documentation. Documentation is for all from beginners to experts, but the underlying mechanism is what we beginners try to understand. Thank you. – invinciblemuffi Jul 15 '21 at 05:53
  • @invinciblemuffi . I have updated my answer to be complete and made some examples to help. I see you've already found your solution using state lifting, however at some point you probably will want to move to global state management. So I hope the above helps. – Jazz Jul 15 '21 at 13:32
  • Thanks a lot for your inputs. – invinciblemuffi Jul 15 '21 at 17:11
0

I stumbled upon this question after searching a lot

How to pass state back to parent in React?

This is the explanation and answer that worked https://stackoverflow.com/a/67084024/3807542

invinciblemuffi
  • 908
  • 1
  • 11
  • 22