I want to send the value of an inputbox useing useContext
so i managed to create a context.js as fallow
context.js
import {createContext} from 'react'
const menuContext = createContext('')
export {menuContext}
then use it in menu.js
import React , {useState} from 'react'
import { menuContext } from './helper/context'
const Menu = () => {
const [text, setText] = useState('')
return (
<div>
<nav className='navbar navbar-dark bd-dark' dir='rtl'>
<menuContext.Provider value={text}>
<form className='form-inline'>
<input
className="form-control mr-sm-2"
type="search" placeholder="جستجوی نام کالا"
aria-label="Search"
onChange={ (event) =>{
setText(event.target.value)
}}
/>
</form>
</menuContext.Provider>
</nav>
</div>
)
}
export default Menu;
but in home.js where i want to use the value of inputbox for filtering products i did not get it
what am i missing?
import React , {useState, useEffect, useContext} from 'react'
import { getProducts } from './helper/Coreapicalls';
import Base from './Base';
import Card from './Card';
import "../styles.css"
import { menuContext } from './helper/context';
export default function Home () {
const [products, setProducts] = useState([]);
const [filteredProducts, setFilteredProducts] = useState([])
const [error, setError] = useState(false);
const [searchIsPresent, setSearchIsPresent] = useState(true);
const searchInput = useContext(menuContext)
const loadAllProducts = () => {
getProducts()
.then((data) =>{
if (data.error){
setError(data.error);
console.log(error);
}
else{
setProducts(data);
}
})
}
useEffect(() => {
loadAllProducts()
}, []);
function filterItems(arr, query) {
return arr.filter((el) => el['subbranch3'].toLowerCase().includes(query.toString().toLowerCase()));
}
const loadFilteredProducts = () => {
setFilteredProducts(filterItems(products, searchInput))
// if (filteredProducts.length !== 0) {
// setSearchIsPresent(true)
// }else{
// setSearchIsPresent(false)
// }
}
useEffect ( () => {
loadFilteredProducts()
}, [searchInput])
const showSearchResult = searchIsPresent =>{
return(
searchIsPresent &&
<div className="row">
{filteredProducts.map((fProduct, index) =>{
return(
<div key={index} className='col-4 mb-4'>
<Card product={fProduct}/>
</div>
)
})}
</div>
)
}
return (
<Base title='صفحه اصلی' description='به فروشگاه اینترنتی خوش آمدید'>
<div>
{showSearchResult(searchIsPresent)}
</div>
<div className="row">
{products.map((product, index) =>{
return(
<div key={index} className='col-4 mb-4'>
<Card product={product}/>
</div>
)
})}
</div>
</Base>
);
}
when i set menuContext manually in context.js i get the result back but if i input something in textinput nothing brought back as resutl.
any help would be appriciated
Thanks
2
Answers
Your
Home
component needs to be a child element of the Context Provider in order to use its value. I can’t tell from your question what the component hierarchy looks like, but I’m guessing it’s something likeI suggest you make the state part of a new component that wraps the provider:
then structure your app like
Your
menuContext.Provider
wraps theinput
element, but not theHome
component. If you want to share state betweenMenu
andHome
, both components must be children of themenuContext.Provider
Initialise the state in the MenuContext:
Wrap all components that need to access the state with the Provider:
Access the state via
useContext
:If you think it feels a bit clumsy to share the setMenu function via a Context (especially if you want to share more then one setter), consider to
useReducer
instead ofuseState
– then you only need to share a single dispatcher function for all state manipulation.