Search code examples
reactjsevent-handlingreact-state-management

how to know which "child" checkbox is selected in reactjs


i am new to React and i hope this doesn't sound stupid. a little bit of context here: i have a ExerciseCard component that has a checkbox,(and other stuff), this component is rendered inside CreateNewWorkout and here i do fetch DATA from an API, so now i want to get all the ExerciseCard components that has its checkBox selected in a list that has the name of that component (in the state it's called 'name' and in the api it's called 'exerciseName').

here is my code
the CreateComponent

import React from "react";
import ExerciseCard from "../component/ExerciseCard";
import { Row } from "antd";

import WorkoutModal from "../component/WorkoutModal";

class CreateNewWorkout extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.changed = this.changed.bind(this);
  }
  // this is the onChange event handlet
  changed = (e) => {
    console.log(e.target.checked);
  };
  async componentDidMount() {
    let response = await fetch("http://localhost:1337/calisthenics-exercices");

    const data = await response.json();
    // i used "objecto" to store an array of objects in state later
    const objecto = [];

    data.map((item) =>
      objecto.push({
        id: item.id,
        name: item.exerciceName,
        discription: item.discription,
        //  the json file has another object file called 'type' inside it for every item
        type: item.type.type,
        imageURL: item.imgURL,
        youtubeURL: item.youtubeURL,
      })
    );
    this.setState(objecto);
  }

  render() {
    return (
      <>
        <div
          style={{
            position: "fixed",
            bottom: 0,
            zIndex: 2,
          }}
        >
          <WorkoutModal></WorkoutModal>
        </div>
        <Row>
          {Object.entries(this.state).map((item) => (
            <ExerciseCard
              title={item[1].name}
              type={item[1].type}
              key={item}
              description={item[1].discription}
              // image={item[1].imageURL}
              youtubeURL={item[1].youtubeURL}
              //changed for onChange event
              changed={this.changed}
            ></ExerciseCard>
          ))}{" "}
          }
        </Row>
        {console.log(this.state)}
      </>
    );
  }
}

export default CreateNewWorkout;

the ExerciseCard if you need it

import React from "react";
import { Col } from "antd";

import ExerciseModal from "./ExerciseModal";
import { Card, Tag, Checkbox } from "antd";
//import Title from "antd/lib/skeleton/Title";
//import { formatCountdown } from "antd/lib/statistic/utils";

const { Meta } = Card;
function ExerciseCard(props) {
  function tagColor() {
    switch (props.type) {
      case "core":
        return "magenta";
      case "lower body":
        return "volcano";
      case "horizontal push":
        return "cyan";
      case "horizontal pull":
        return "blue";
      case "vertical pull":
        return "geekblue";
      case "vertical push":
        return "purple";
      default:
        return "black";
    }
  }

  return (
    <Col xs={12} sm={8} md={6} lg={4}>
      <Card>
        <Meta title={props.title} />

        <Tag
          style={{ position: "absolute", top: 0, left: 0 }}
          color={tagColor()}
        >
          {props.type}
        </Tag>

        <Checkbox
          onChange={props.changed}
          style={{
            padding: "20px 0 0 0",
          }}
        ></Checkbox>
        <ExerciseModal
          title={props.title}
          description={props.description}
          youtubeURL={props.youtubeURL}
        ></ExerciseModal>
      </Card>
    </Col>
  );
}

export default ExerciseCard;



Solution

  • You could access the checkbox, using e.target If you need something particular as user-defined data (such as id, name or something else, you could define your change function as following:

     changed = (e, title) => {
        console.log(e.target.checked);
      };
    

    Please note, that you have already defined the function as arrow function and you don't have to bind this in your constructor.

    Then pass the function to ExcerciseCard the same way you are doing it now. Finally call the function in the following way:

     <Checkbox
              onChange={e => props.changed(e, props.title)}
              style={{
                padding: "20px 0 0 0",
              }}
            ></Checkbox>
    

    I wrote an example with title, but feel free to change it, so it fits your needs.