I'm relatively new to React and am trying to set the state of an object inside the child component(SportTile) for the onclick event. I'm comfortable updating the state of a single variable by using individual useState() hooks but, that is a cumbersome task when you have a lot of variables. So I used an object named : isClicked which stores a boolean value for various sports on whether they are selected by the user or not.
The functionality that I'm looking for is, whenever a SportTile gets clicked on, its isClicked["sportname"] value is set to true and the rest are set to false. Only one sport can be true at once.
Upon console logging the isClicked object in the onclick() function, I got the desired values but they weren't updated in the Parent component's(Booking) h1 tag
import React from 'react';
import SportTile from '../SportTile';
import './booking.css';
import { useState } from 'react';
import SportsSoccerRoundedIcon from '@mui/icons-material/SportsSoccerRounded';
import SportsBasketballRoundedIcon from '@mui/icons-material/SportsBasketballRounded';
import SportsVolleyballIcon from '@mui/icons-material/SportsVolleyball';
import SportsTennisIcon from '@mui/icons-material/SportsTennis';
const Booking = () => {
const [isClicked, setIsClicked] = useState({
Football: false,
Basketball: false,
Volleyball: false,
Tennis: false,
});
return (
<div className='booking'>
<div className='booking__body'>
<div className='booking__left'>
<h1>SELECT SPORT</h1>
<SportTile
sportname={'Football'}
icon={<SportsSoccerRoundedIcon />}
clicked={setIsClicked}
isClicked={isClicked}
// test={setTestclicked}
// istestClicked={istestClicked}
/>
<SportTile
sportname={'Basketball'}
icon={<SportsBasketballRoundedIcon />}
clicked={setIsClicked}
isClicked={isClicked}
/>
<SportTile
sportname={'Volleyball'}
icon={<SportsVolleyballIcon />}
clicked={setIsClicked}
isClicked={isClicked}
/>
<SportTile
sportname={'Tennis'}
icon={<SportsTennisIcon />}
clicked={setIsClicked}
isClicked={isClicked}
/>
<h1>Football : {isClicked.Football.toString()} </h1>
<h1>Basketball : {isClicked.Basketball.toString()} </h1>
<h1>Volleyball : {isClicked.Volleyball.toString()} </h1>
<h1>Tennis : {isClicked.Tennis.toString()} </h1>
</div>
<div className='booking__right'>Right Side</div>
</div>
</div>
);
};
export default Booking;
import { Button } from '@mui/material';
import React from 'react';
import './sportTile.css';
const SportTile = ({
sportname,
icon,
clicked,
isClicked,
}) => {
function onclick() {
Object.keys(isClicked).map((key) => {
if (key == sportname) {
isClicked[key] = true;
} else {
isClicked[key] = false;
}
});
clicked(isClicked);
console.log(isClicked);
}
return (
<Button className='sportname__button' onClick={onclick}>
<div className='sportname__buttonColumn'>
{icon}
{sportname}
</div>
</Button>
);
};
export default SportTile;
Maybe I'm missing the obvious but would appreciate anyone who could point me in the right direction
CodePudding user response:
You should never pass the original setState method. create a new method in the Booking component:
const setIsClickedWrapper = (sportKey) = {
setIsClicked((isClicked) => Object.keys(isClicked).map((key) => sportKey === key)
}
and in the SportTile component just call:
const onclick = () => { setIsClickedWrapper(sportname) }
but I think it will be better if isClicked will be just a string of the current clicked sport key and then it's enough:
const setIsClickedWrapper = (sportKey) = {
setIsClicked(sportKey)
}