简体   繁体   中英

React - setState in child through props

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

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)
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM