Home > other >  React - setState in child through props
React - setState in child through props

Time:01-05

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)
} 
  •  Tags:  
  • Related