1

I want to push element in array of state variable on each click of check box. The problem is when i click on checkbox the value get pushed into array but when i click another checkbox array washout old value and only one value is present in it.

export default class Demo extends Component{
    constructor(props){
        super(props);
        this.state = {
            attachmentList : []
        };
    }
    addAttachmentid = (e) => {

        console.log("1st",this.state.attachmentList)
        if(e.target.checked){
            this.setState({

                 attachmentList:this.state.attachmentList.push(e.target.value)
            });
        }
        else{
            this.setState({
                attachmentList:this.state.attachmentList.pop(e.target.value)
            });
        }

        console.log("attachmentlist",this.state.attachmentList)
    }
        render(){
             return (
                   <input type="checkbox" value="20" onChange={this.addAttachmentid} />
                   <input type="checkbox" value="21" onChange={this.addAttachmentid} />
                   <input type="checkbox" value="22" onChange={this.addAttachmentid} />
             )
        }
}

5 Answers 5

1

Its because pop method returns the removed item doesn't return the whole array. You could use filter to do this.

const filteredList = this.state.attachmentList.filter(item => item !== e.target.value);

// set this in the state.

Pop Method Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop

Sign up to request clarification or add additional context in comments.

1 Comment

no Yash it's not because of pop. if checkbox is checked after clicking it it will push otherwise it will pop
1

We should never mutate state(array in your case)

Here is the working code

import React, { Component } from "react";
import ReactDOM from "react-dom";

class App extends Component {
  state = {
    attachmentList: [],
    checkBoxValue: ["20", "21", "22"]
  };
  addAttachmentid = ({ target: { value, checked } }) => {
    console.log("1st", this.state.attachmentList);
    let attachement = [...this.state.attachmentList];

    if (checked) {
      attachement.push(value);
    } else {
      attachement.pop(value);
    }
    console.log("2nd", attachement);
    this.setState({
      attachmentList: attachement
    });
  };

  render() {
    return (
      <>
        {this.state.checkBoxValue.map(value => {
          return (
            <input
              type="checkbox"
              value={value}
              onChange={this.addAttachmentid}
            />
          );
        })}
      </>
    );
  }
}

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

Hope it helps!!!

4 Comments

By doing let attachement = [...this.state.attachmentList]; you're relying on the current value of state for setting a new one. However, since setState works async, it might have been changed meanwhile by some other function calls. It's safer to use functional form of setState.
Yes you are correct, it's always safer in a complex application to use functional form, but for small functions in which state is used only in that function, I prefer to use object style instead of functional as it supports better readability of code for me. In the end it's about personal preference and complexity of state sharing.
still not solved issue , did you get what exactly output i need ? i need 20,21,22 in attachmentList after checking all three checkboxes
Try codesandbox link as you check/uncheck on checkbox you will see those values printed and popped.
0

Do not mutate the state directly, use array spread and filter instead:

  addAttachmentid = e => {
    console.log("1st", this.state.attachmentList);
    const { checked, value } = e.target;

    this.setState(
      state => {
        if (checked) {
          return {
            attachmentList: [...state.attachmentList, value]
          };
        }
        return {
          attachmentList: state.attachmentList.filter(
            attachment => attachment !== value
          )
        };
      },
      () => {
        console.log("attachmentlist", this.state.attachmentList);
      }
    );
  };

A few other things:

  • Use functional form of setState if your next state depends on the previous state
  • If you want to check the new state right after setting it, use callback function to the setState.

I've recently wrote a post about these and a few other common mistakes with React.

Comments

0

Please filter out the elemnt when we un check

attachement = this.state.attachmentList.filter((item) =>  item !== e.target.value)

Comments

0

You could potentially just update the state, but spread it's previous state:

this.setState(prevState => ({
    attachmentList: [...prevState.attachmentList, e.target.value],
}));

Then, when you want to remove it you can do a similar thing:

this.setState(prevState => ({
    attachmentList: prevState.attachmentList.filter(value => value !== e.target.value),
}));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.