0

So I can get the button through the event when it is clicked on. But when I do a filter, it does not remove the said button.

So I have my array in the constructor():

constructor()
{   
    super();
    this.options = [ 1, 2, 3, 4, 5]; 
    this.temp_option = []; 
    this.delete_me = this.delete_me.bind(this);
    this.buttons = [<button key="0" onClick={this.delete_me}/>,<button key="1" onClick={this.delete_me}/>];
    this.state = { buttons: this.buttons };
}

then I have the function:

delete_me(e)
{   
    console.log(e.target);
    this.buttons = this.buttons.filter((item) => item != e.target);
    console.log(this.buttons);
}

However this.buttons still has two elements in it.

I thought about another way to delete it and it was to use the 'key', but I can't seem to find anything about getting key value.

5
  • 1
    try this this.delete_me.bind(this) Commented Jan 3, 2017 at 4:34
  • You should be using state for this, so not this.buttons, but rather this.state.buttons via setState Commented Jan 3, 2017 at 5:02
  • @uzaif Ah forgot to mention I did it in the constructor. Will add it to clarify things. Commented Jan 3, 2017 at 5:11
  • @Chris I just wanted to test and see if buttons were being deleted first, which they aren't, so using setState wouldn't help at this point yet. Commented Jan 3, 2017 at 5:11
  • See my answer below, it should make more sense Commented Jan 3, 2017 at 5:12

2 Answers 2

4

The approach you are currently taking isn't really "react". You need to think more about a change in state rather than altering the dom directly.

One approach would be:

class App extends React.Component {
  constructor(){
    super();
    this.state ={
      visibleButtons: [ 11, 22, 33, 44 ],
      buttons: {
        11: {
          label: "Foo",
        },
        22: {
          label: "Bar"
        },
        33: {
          label: "Cow",
        },
        44: {
          label: "Pig"
        },        
      },
    }
  }

  onDelete(deletedId) {
    this.setState({
       visibleButtons: this.state.visibleButtons.filter(id => id !== deletedId)
    });
  }

  render () {                                        
    return (
      <div>
        { this.state.visibleButtons.map(buttonId => (
          <button key={buttonId} onClick={() => this.onDelete(buttonId)}>{this.state.buttons[buttonId].label}</button>
        )) }   
      </div>
    );
  }
}

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

http://codepen.io/cjke/pen/RKwWwZ?editors=0010


Edit

An example showing adding and removing. The unique id is pretty primitive, and doesn't actively check for what is there, but you should get the gist:

class App extends React.Component {
  constructor(){
    super();
    this.onAdd = this.onAdd.bind(this);
    this.onChange = this.onChange.bind(this);

    this.state ={
      value: '',
      uniqueId: 100,
      visibleButtons: [ 11, 22, 33, 44 ],
      buttons: {
        11: {
          label: "Foo",
        },
        22: {
          label: "Bar"
        },
        33: {
          label: "Cow",
        },
        44: {
          label: "Pig"
        },        
      },
    }
  }

  onDelete(deletedId) {
    this.setState({
       visibleButtons: this.state.visibleButtons.filter(id => id !== deletedId)
    });
  }

  onChange(e) {
    this.setState({ value: e.target.value });
  }

  onAdd(e) {
    this.setState({
      uniqueId: this.state.uniqueId + 1,
      value: '',
      buttons: {
        ...this.state.buttons, 
        [this.state.uniqueId]: { 
          label: this.state.value,
        }
      },
      visibleButtons: [...this.state.visibleButtons, this.state.uniqueId],
    });
  }

  render () {                                        
    return (
      <div>
        <div>
        { this.state.visibleButtons.map(buttonId => (
          <button key={buttonId} onClick={() => this.onDelete(buttonId)}>{this.state.buttons[buttonId].label}</button>
        )) } 
        </div>
        <br/>
        <div>
          <input onChange={this.onChange} value={this.state.value}/><button onClick={this.onAdd}>+</button>
        </div>
      </div>
    );
  }
}

ReactDOM.render(<App/>,document.getElementById('root'));
Sign up to request clarification or add additional context in comments.

11 Comments

Interesting answer, however I am doing this dynamically. I also have another button which can 'grow' the number of classes in the array. I was thinking along the lines of the id, but is there a way to access the 'key' attribute instead?
This is dynamic. You can easily easily add to it simply by pushing into the button array state
kind of wanted to avoid having to resort to ids since imo, it can get clunky. I used this logic in Angular 2 fine, and was just hoping I could transfer it over (could remove just using the button's this). But if this is the only way in react, then I'll give it a shot first.
Thats cool. Be careful relying on internal properties such as _targetInst though. I don't mind which answer you accept but you should really try to embrace the react way when using react - it will make your life sooo much easier.
In es6 if a function has only one statement, you can omit the return statement. So const f = (a) => a + 2. If that statement happens to occur over multiple lines, I use this form const f = (a) => (a + 2) as a) you can code collapse multiple lines, and b) the intention is clearer
|
2

First of all, you need to bind this to the scope of your callback function. If you want to access the react object instance used to render the button from the synthetic event, you can do so using the private variable _targetInst.

class Buttons extends React.Component{

  constructor(props) {
    super(props);
    this.delete_me = this.delete_me.bind(this);
        this.state = {
        buttons : [<button key="0" onClick={this.delete_me}>0</button>,<button key="1" onClick={this.delete_me}>1</button>]
    };
  }

  delete_me(e){
    const buttons = this.state.buttons.filter((button) => button != e._targetInst._currentElement);
    this.setState({ buttons });
  }   

  render() {
    return <div>{this.state.buttons}</div>;
  }
};

ReactDOM.render(
  <Buttons />,
  document.getElementById('container')
);

However, as Chris mentioned, your approach is not very much in line with the React patterns, and you should avoid accessing private methods or properties (usually named with an underscore)

1 Comment

I have a similar question at stackoverflow.com/questions/41435474/… but it's in regard to a component itself, which is passed. This time there is no event. Do you think you could have a look?

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.