I'm stuck trying to filter an array of objects conditionally in React. I have everything set up and working as I believe it should, but I think I'm just mixing a few things up in my inexperience.
Ultimately I want to have all my objects rendered at start, but then filter according to checkboxes selected. For some reason the conditional statement for what to render is not working at all, and while I'm able to get my checkboxes state stored and changed with each click, I am not able to get it to filter.
Here is my code for the component(StoneDisplay.js) This renders the list of checkboxes for filtering the list of stones to display, as well as the container that displays the list of stones. It contains instances of State for my checkboxes, along with the conditional rendering code for which stones to display. To state the obvious, without the conditional code, all items render fine.
import React, { useState } from 'react'
import StoneFilter from '../StoneFilter/StoneFilter'
import Stone from '../Stone/Stone'
import './StoneDisplay.css'
const StoneDisplay = ({ stones }) => {
const [stoneType, setStoneType] = useState({})
const [stoneColor, setStoneColor] = useState({})
console.log('stones in StoneDisplay: ', stones)
console.log('stoneType in Display: ', stoneType)
console.log('stoneColor in Display: ', stoneColor)
const stonesToShow = (stoneType && stoneColor === {}) ?
stones :
stones.filter(item => item.type === stoneType.checked && stoneColor.checked)
//console.log('item.type: ', item.type)
console.log('stoneType.checked: ', stoneType)
return (
<section className="stone">
<StoneFilter
stoneType={stoneType}
setStoneType={setStoneType}
stoneColor={stoneColor}
setStoneColor={setStoneColor}
/>
<div className="stone__carousel">
{stonesToShow.map((stone) =>
<Stone
key={stone.id}
stone={stone}
/>
)}
</div>
</section>
)
}
export default StoneDisplay
*referring to: console.log('stoneType.checked: ', stoneType) In my limited understanding and what I believe I set in the handler, stoneType.checked should return a boolean, but it returns undefined. When I just log StoneType I get: {Granit: true, Onyx: true, Travertin: true}
Here is the component containing my checkboxes. I keep coming back here as I believe my problems could be from how I'm handling/saving the state. I am unable to determine how/why though..
import React from 'react'
import StoneFilterListItem from '../StoneFilterListItem/StoneFilterListItem'
import checkboxesType from './checkboxesType'
import checkboxesColor from './checkboxesColor'
import './StoneFilter.css'
const StoneFilter = ({ stoneType, setStoneType, stoneColor, setStoneColor }) => {
const handleTypeChange = event => {
setStoneType({
...stoneType,
[event.target.value]: event.target.checked
})
console.log('checked types: ', stoneType)
}
const handleColorChange = event => {
setStoneColor({
...stoneColor,
[event.target.value]: event.target.checked
})
console.log('checked colors: ', stoneColor)
}
return (
<div className="stone__nav">
<h2 className="stone__nav-head">Type</h2>
<div className="stone__nav-list">
{checkboxesType.map(item => (
<label className="stone__nav-var" key={item.key}>
{item.value}
<StoneFilterListItem
id={item.id}
name={item.name}
value={item.value}
checked={stoneType[item.value]}
onChange={handleTypeChange}
/>
<span className="checkmark"></span>
</label>
))}
</div>
<h2 className="stone__nav-head">Couleur</h2>
<div className="stone__nav-list">
{checkboxesColor.map(item => (
<label className="stone__nav-var" key={item.key}>
{item.value}
<StoneFilterListItem
id={item.id}
name={item.name}
value={item.value}
checked={stoneColor[item.value]}
onChange={handleColorChange}
/>
<span className="checkmark"></span>
</label>
))}
</div>
</div>
)
}
export default StoneFilter
Here is my component for each checkbox list item:
import React from 'react'
const StoneFilterListItem = ({ type = "checkbox", id, name, value, checked = false, onChange }) => {
console.log('Filter Item: ', id, checked)
return (
<input type={type} id={id} name={name} value={value} checked={checked} onChange={onChange} />
)
}
export default StoneFilterListItem
Here is the checkboxesType.js used for filtering type, chcekboxesColor,js is similar so don't believe I need to post that too.
const checkboxesType = [
{
id: "Marbre",
key: "checkbox1",
label: "marbre",
value: "Marbre"
},
{
id: "Granit",
key: "checkbox2",
label: "granit",
value: "Granit"
},
{
id: "Onyx",
key: "checkbox3",
label: "onyx",
value: "Onyx"
},
{
id: "Travertin",
key: "checkbox4",
label: "travertin",
value: "Travertin"
},
{
id: "Quartz",
key: "checkbox5",
label: "quartz",
value: "Quartz"
},
{
id: "Terrazzo",
key: "checkbox6",
label: "terrazzo",
value: "Terrazzo"
}
]
export default checkboxesType
Adding App.js just incase too:
import React, { useState, useEffect } from 'react'
import Header from '../Header/Header'
import NavBar from '../NavBar/NavBar'
import About from '../About/About'
import StoneDisplay from '../StoneDisplay/StoneDisplay'
import Contact from '../Contact/Contact'
/* import stoneService from '../../services/stones' */
import axios from 'axios'
import './App.css'
const App = () => {
const [stones, setStones] = useState([])
useEffect(() => {
console.log('effect');
axios
.get('http://localhost:3001/stones')
.then(response => {
console.log('promise fulfilled')
setStones(response.data)
})
}, [])
console.log('render', stones.length, 'stones')
return (
<div className="appContainer">
<Header />
<NavBar />
<About />
<StoneDisplay stones={stones} />
<Contact />
</div>
)
}
export default App
Any help or guidance towards what I'm doing wrong here would be greatly appreciated.
Aucun commentaire:
Enregistrer un commentaire