I have a set of buttons in a child component where when clicked set a corresponding state value true or false. I have a useEffect hook in this child component also with dependencies on all these state values so if a button is clicked, this hook then calls setFilter which is passed down as a prop from the parent...
const Filter = ({ setFilter }) => {
const [cycling, setCycling] = useState(true);
const [diy, setDiy] = useState(true);
useEffect(() => {
setFilter({
cycling: cycling,
diy: diy
});
}, [cycling, diy]);
return (
<Fragment>
<Row>
<Col>
<Button block onClick={() => setCycling(!cycling)}>cycling</Button>
</Col>
<Col>
<Button block onClick={() => setdIY(!DIY)}>DIY</Button>
</Col>
</Row>
</Fragment>
);
};
In the parent component I display a list of items. I have two effects in the parent, one which does an initial load of items and then one which fires whenever the filter is changed. I have removed most of the code for brevity but I think the ussue I am having boils down to the fact that on render of my ItemDashboard the filter is being called twice. How can I stop this happening or is there another way I should be looking at this.
const ItemDashboard = () => {
const [filter, setFilter] = useState(null);
useEffect(() => {
console.log('on mount');
}, []);
useEffect(() => {
console.log('filter');
}, [filter]);
return (
<Container>..
<Filter setFilter={setFilter} />
</Container>
);
}
I'm guessing, you're looking for the way to lift state up to common parent.
In order to do that, you may bind event handlers of child components (passed as props) to desired callbacks within their common parent.
The following live-demo demonstrates the concept:
const { render } = ReactDOM,
{ useState } = React
const hobbies = ['cycling', 'DIY', 'hiking']
const ChildList = ({list}) => (
<ul>
{list.map((li,key) => <li {...{key}}>{li}</li>)}
</ul>
)
const ChildFilter = ({onFilter, visibleLabels}) => (
<div>
{
hobbies.map((hobby,key) => (
<label {...{key}}>{hobby}
<input
type="checkbox"
value={hobby}
checked={visibleLabels.includes(hobby)}
onChange={({target:{value,checked}}) => onFilter(value, checked)}
/>
</label>))
}
</div>
)
const Parent = () => {
const [visibleHobbies, setVisibleHobbies] = useState(hobbies),
onChangeVisibility = (hobby,visible) => {
!visible ?
setVisibleHobbies(visibleHobbies.filter(h => h != hobby)) :
setVisibleHobbies([...visibleHobbies, hobby])
}
return (
<div>
<ChildList list={visibleHobbies} />
<ChildFilter onFilter={onChangeVisibility} visibleLabels={visibleHobbies} />
</div>
)
}
render (
<Parent />,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With