简体   繁体   中英

How to toggle boolean specific states?

I want to add to Chip an startIcon={<Icon />} when click on a Chip. The state of the icon is managed by chipsState.

In this code, the state of all chips would change. How can I change only the chipsState of the element that is clicked?

In this code, the state of all chips will change. How can I change only the chipsState of the element that is clicked?

const Modal:React.FC<Props>= (props) => {
  const {modalData} = props;
  const [chipsState, setChipsState] = useState(false);

  const onChipClick = (element:any) => {
   setChipsState(chipsState => !chipsState);  
  }

  return (
    <div>
         {
           modalData.symtoms.map((element:any, index:number) => (
            <div key={index}>
             <Chip onClick={() => onChipClick(element)} startIcon={chipsState && <Icon />}>{element.description}</Chip>
            </div>
        ))}
    </div>
  );
}


export default Modal;

You can achieve your desired output by changing chipState state from boolean to object.

So first let's change to object state instead of boolean

const [chipsState, setChipsState] = useState({});

Now we will change onChipClick function to change value of selected chip state

const onChipClick = (element:any) => {
   setChipsState({...chipsState, chipsState[element]: !chipsState[element]});  
  }

And finally we will read correct value of each chipsState element.

<Chip onClick={() => onChipClick(element)} startIcon={chipsState[element] && <Icon />}>{element.description}</Chip>

To handle local state (and better testing), you should create a new custom Chip component with dedicated chipState.

interface CustomChipProps {
   description: string
}

const CustomChip = (props: CustomChipProps) => {
  const [chipState, setChipState] = useState(false);
   
  return <Chip onClick={() => setChipState(prev => !prev)} startIcon={chipState && <Icon />}>{props.description}</Chip>;
}



const Modal:React.FC<Props>= (props) => {
  const {modalData} = props;

  return (
    <div>
         {
           modalData.symtoms.map((element:any, index:number) => (
            <div key={index}>
             <CustomChip description={element.description} />
            </div>
        ))}
    </div>
  );
}


export default Modal;

You can try like the following

import React, { useState, useCallback } from "react";
import ReactDOM from "react-dom";
import { Grid, Row } from "react-flexbox-grid";

const ChipSet = ({ symtomsData }) => {
  const data = symtomsData.map((symtom) => ({ ...symtom, isSelcted: false }));

  const [chipSets, setChipSets] = useState(data);

  const onSelectChipSet = useCallback(
    (e, index) => {
      const updatedChipSets = chipSets.map((chip, i) =>
        i === index ? { ...chip, isSelcted: e.target.checked } : chip
      );
      setChipSets(updatedChipSets);
    },
    [chipSets]
  );

  console.log("chipSets", chipSets);
  return (
    <div>
      <h1>Symtoms Data</h1>
      {chipSets.map((x, i) => (
        <div key={i}>
          <label>
            <input
              onChange={(e) => onSelectChipSet(e, i)}
              type="checkbox"
              value={x.isSelcted}
            />
            {x.description}
          </label>
        </div>
      ))}
    </div>
  );
};

class App extends React.Component {
  render() {
    const symtomsData = [
      {
        description: "mild"
      },
      {
        description: "cold"
      }
    ];
    return (
      <Grid>
        <Row>
          <ChipSet symtomsData={symtomsData} />
        </Row>
      </Grid>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

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