Khan Asfi Reza
Khan Asfi Reza

Reputation: 691

React changing the state when the button is clicked

I am creating a react app where I want to output possible diseases if the symptoms button is clicked.

state = {
  user_symptoms = [],
  user_possible_disease = []
}

Disease = {
    'aids': ['fever', 'cough', 'dysentery'],
    'corona': ['fever', 'cough', 'breathe_problem'],
    'heart_attack': ['angina', 'pain', 'head_ache'],
    [A bunch of objects like this]
}

render() {
  return(
    <div>
      <p>{{this.state.user_possible_disease.map((key, index) => {
        return <h2 key={index}>{Object.keys(key)}</h2>
      })}}</p>
      <button value='cough' className='unclicked' />
      <button value='angina' className='unclicked' />
      <button value='pain' className='unclicked' />
      <button value='breathe_problem' className='unclicked' />
    </div>
  )
}

So if I click any button of the symptoms, then the possible disease object with any of those symptoms will be added in the user_possible_dissease Suppose I have clicked on the cough button so the user_possible_disease: [{'aids': ['fever', 'cough', 'dysentery'], 'corona': ['fever', 'cough', 'breathe_problem'],}] will be like this and if I unclick the button the possible diseases will be gone from the state.

Upvotes: 0

Views: 960

Answers (3)

Todor Popov
Todor Popov

Reputation: 181

First, I'd recommend storing the selected diseases in a JSON, instead of array.

state = {
  user_possible_disease = {}
}

Then define the onButtonClick function:

onButtonClick (e) {
    const disease = e.target.value;
    const isActive = this.state.user_possible_disease[disease];
    if (isActive) {
       // Remove this disease from state;
       const { [disease]: _, ...restDiseases } = this.state.user_possible_disease;
       this.setState(restDiseases);
    } else {
       // Add this disease to state;
       this.setState({ 
          ...this.state.user_possible_disease, 
          [disease]: Disease[disease] 
       })
    }
}

And at last attach the onButtonClick function to each button:

  <button 
     value='cough' 
     onClick={this.onButtonClick}
     className={this.state.user_possible_disease['cough'] ? 'clicked' : 'unclicked'} />

Also one tip: Try not to duplicate any code/values. For example in the moment user clicks the button, we store the very same array of symptoms into the state. And that array exists both in the Disease constant AND in the state. A better practice would be just to store the selected disease keys in thee state, like: ['aids', 'corona'], and then when user submits the form, to generate they request payload, by looping the selected diseases (from state), find their related symptoms and push them to they payload. This way you lift off the component's state, e.g. it holds less data.

Upvotes: 1

HMR
HMR

Reputation: 39250

I guess you wanted to show diseases for given symptoms. You can do the following:

class App extends React.Component {
  state = {
    user_symptoms: [],
    user_possible_disease: [],
  };

  Disease = {
    aids: ['fever', 'cough', 'dysentery'],
    corona: ['fever', 'cough', 'breathe_problem'],
    heart_attack: ['angina', 'pain', 'head_ache'],
  };
  toggleSymptom = (e) => {
    let user_symptoms = this.state.user_symptoms;
    if (user_symptoms.includes(e.target.value)) {
      //we already have this symptom then remove it
      user_symptoms = user_symptoms.filter(
        (s) => s !== e.target.value
      );
    } else {
      //we dont have the symptom so add it
      user_symptoms = [...user_symptoms, e.target.value];
    }
    this.setState({
      user_symptoms,
      user_possible_disease: user_symptoms.length //do we have symptoms
        ? Object.entries(this.Disease) //look for deseases
            .filter(([, diseaseSymptom]) =>
              user_symptoms.every((
                s //all symptoms are symptoms of disease
              ) => diseaseSymptom.includes(s))
            )
            .map(([key]) => key) //only need key of the object
        : [],
    });
  };

  render() {
    return (
      <div>
        <ul>
          {this.state.user_possible_disease.map((d) => (
            <li key={d}>{d}</li>
          ))}
        </ul>
        <button
          value="cough"
          className="unclicked"
          onClick={this.toggleSymptom}
        >
          cough
        </button>
        <button
          value="angina"
          className="unclicked"
          onClick={this.toggleSymptom}
        >
          angina
        </button>
        <button
          value="pain"
          className="unclicked"
          onClick={this.toggleSymptom}
        >
          pain
        </button>
        <button
          value="breathe_problem"
          className="unclicked"
          onClick={this.toggleSymptom}
        >
          breathe problem
        </button>
      </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>

Upvotes: 1

Jap Mul
Jap Mul

Reputation: 18739

Add an onClick event to the button(s) and then set the right diseases based on the value of the clicked button.

const Disease = {
  corona: ["fever", "cough", "breathe_problem"]
};

class App extends React.Component {
  state = {
    user_possible_disease: []
  };

  // This function will be called for all buttons
  setPossibleDiseases = (event) => {
    // The Disease[event.target.value] fetches the diseases from the Diseases object
    this.setState({
      user_possible_disease: Disease[event.target.value]
    });
  };

  render() {
    return (
      <div>
        <div>
          {this.state.user_possible_disease.map((disease, index) => {
            return <h2 key={index}>{disease}</h2>;
          })}
        </div>
        <button
          value="corona"
          className="unclicked"
          onClick={this.setPossibleDiseases}
        >
          Corona
        </button>
      </div>
    );
  }
}

In your example you have a { to much in {{this.state.user_poss.... and also an h2 cannot/should not be inside a p.

Upvotes: 0

Related Questions