I’m working on building an e-commerce website in React. In which, there will be a navigation bar with all the categories and once a user clicked on a specific category, it will render all the products that belongs to the checked category in the same page. In the project I have two .js
files which are NavBar.js
where it contains all the stuff for the navigation bar and AllItems.js
where all products are rendered.
My problem now, is that onclick
in NavBar.js
doesn't render AllItems.js
. It works with console.log("sss")
but it doesn't work with <AllItems/>
Here is my code in NavBar.js
function NavBar() {
const [allCategories, setAllCategories] = useState([])
const [currency, setCurrency] = useState([])
useEffect(() => {
fetchAnyQuery(
`
query{
categories{
name
}
}
`).then(data => {
setAllCategories( data.data.categories )
})
},[])
// for currency options
useEffect(() => {
fetchAnyQuery(`
query{
currencies
}
`
).then(data => {
setCurrency(data.data.currencies)
})
},[])
return (
<nav id = "NavBar">
<div id="NavBar-content">
<div className = "leftSide" id = "leftNav">
{allCategories.map((allCategories, index) => {
if (index == 0){
// return a checked tab
return(
<>
<input className='radio-category' id={allCategories.name} type='radio' name="nav" onClick={
function (){
console.log("ssss");
<AllItems/>
}
} checked/>
<label htmlFor={allCategories.name} className='category-label'><h5 className="tab-text">{allCategories.name.toUpperCase()}</h5></label>
</>
)
}
else {
// return unchecked tab
return(
<>
<input className='radio-category' id={allCategories.name} type='radio' name="nav" onClick={ function (){changeCategoryState(allCategories.name); <AllItems/>} } />
<label htmlFor={allCategories.name} className='category-label'><h5 className="tab-text">{allCategories.name.toUpperCase()}</h5></label>
</>
)
}
})}
</div>
<div className = "centerSide">
{/*<a href="/">*/}
{/* /!*<img src={logo} />*!/*/}
{/* Logo*/}
{/*</a>*/}
<button onClick={function (){ console.log(getCategoryState()) }}>
Abo Kalb
</button>
</div>
<div className = "rightSide">
<select className="currencySelector" id="currencySelector">
{currency.map((currency, index) =>{
return(
<option value={ JSON.stringify(currency.indexOf(index)) } > {getSymbolFromCurrency(currency.toString()) " " currency.toString()} </option>
)
})}
</select>
</div>
</div>
</nav>
);
}
export default NavBar;
Also, here is my code for AllItems.js
file:
function AllItems() {
// The state that I want to use in NavBar.js
// const [category, setCategory] = useState([getCategoryState()])
const [products, setProducts] = useState([])
useEffect(() => {
fetchAnyQuery(
`
query{
categories{
name
products{
name
id
}
}
}
`
).then(data => {
// Here I'm trying to do all the required stuff
// console.log(category)
})
},[])
console.log("All Items RENDERED!!")
return (
<>
<h1>{ getCategoryState() }</h1>
<div className="itemContainer" id="itemContainer">
</div>
</>
)
}
export default AllItems;
CodePudding user response:
From what I understood, you want to render different categories' data based on which category is clicked, but you can not call a component on the click, that's not how React works. Instead set a state and render the component conditionally according to the state value, and set the state when the component needs to be rendered.
Assuming that you're fetching your items from a server, you will have to store that data in a state
const [allItems, setAllTems] = useState([])
Then add a state that will help you render your items conditionally
const [showAllItems, setShowAllItems] = useState(false)
In your JSX, use && to render your data when the state gets all the data
<> {showAllItems && <AllItems>} </>
if you're having troubles understanding how this works, I suggest you checking React documentations, it explains very well how you can manipulate the state
CodePudding user response:
Use a parent component to manage the state. When you update the radio input in Nav
update the state, and then filter the data based on that selection.
const { useState } = React;
function Example({ data }) {
const [ items, setItems ] = useState(data);
const [ selection, setSelection ] = useState('');
// When you click a button, set the selection state
function handleClick(e) {
setSelection(e.target.dataset.type);
}
// `filter` out the items you want to display
// based on the selection
function filteredItems() {
return items.filter(item => item.type === selection);
}
return (
<div>
<Nav>
Dairy: <input onClick={handleClick} type="radio" data-type="dairy" name="food" />
Meat: <input onClick={handleClick} type="radio" data-type="meat" name="food" />
Vegetable: <input onClick={handleClick} type="radio" data-type="vegetable" name="food" />
</Nav>
<Items items={filteredItems()} />
</div>
);
};
// `map` over the filtered data
function Items({ items }) {
return items.map(item => <div>{item.name}</div>);
}
function Nav({ children }) {
return children;
}
const data = [
{ name: 'cow', type: 'meat' },
{ name: 'bree', type: 'dairy' },
{ name: 'chicken', type: 'meat' },
{ name: 'sprout', type: 'vegetable' }
];
ReactDOM.render(
<Example data={data} />,
document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>