0

When I click on a delete button, I want to then filter out that ID and re-render the list, but I am getting an annoying error as mentioned in the title.

It will eventually send a request to the server to delete from the database but for now all I want is the item to be removed from the list and the list to show up again without that particular record. It is basically a table with a bunch of records. Each one has a delete button next to it. When you click delete it should remove that item which is what I am trying to do with .filter and then set the state to the new loadedFaq minus the record that was filtered out.

The button:

<Button
  color="purple"
  label="Delete"
  onClick={() => deleteHandler(faq)}
/>

The delete handler:

  const deleteHandler = async (faq) => {
    const originalFaq = loadedFaq; // loadedFaq is the original state
    const loadedFaq = originalFaq.filter((f) => f._id !== faq._id);
    setLoadedFaq(loadedFaq); // set the state to the original state minus the filtered out record
  };

UPDATE:

It doesn't like the fact that I am redeclaring 'loadedFaq'. If I do this it works:

  const deleteHandler = async (faq) => {
    const originalFaq = loadedFaq;
    const loadedFaqTwo = originalFaq.filter((f) => f._id !== faq._id);
    setLoadedFaq(loadedFaqTwo);
  };
user8463989
  • 2,275
  • 4
  • 20
  • 48
  • What do you expect to happen here? The delete handler doesn't really make sense... Is your state variable also called `loadedFaq`? – Brian Thompson May 21 '20 at 19:04
  • Could you please update the question so what we know what you want to do? – Ahsan Ullah May 21 '20 at 19:06
  • It will eventually send a request to the server to delete from the database but for now all I want is the item to be removed from the list and the list to show up again without that particular record. It is basically a table with a bunch of records. Each one has a delete button next to it. When you click delete it should remove that item which is what I am trying to do with `.filter` and then set the state to the new `loadedFaq` minus that record – user8463989 May 21 '20 at 19:06
  • @AhsanUllah, I have done so. Let me know if further clarity is needed. – user8463989 May 21 '20 at 19:07
  • @user8463989 how is the data look like could please provide that or structure of that data? – Ahsan Ullah May 21 '20 at 19:09
  • I think I figured out the issue. It doesn't like that I am using the same variable name again. If I change. See my question for update... – user8463989 May 21 '20 at 19:10
  • Ok so you have attempted to declare a variable with the same name as another variable within scope. Its called shadowing. But since you are declaring a new variable with the same name, you cannot use the outer scoped one anymore, hence the error – Brian Thompson May 21 '20 at 19:10
  • @BrianThompson, so is the solution like what I have done with my latest question edit or is that not the right way to go about it? – user8463989 May 21 '20 at 19:11

2 Answers2

2

loadedFaq is your state, you should not redeclare it. Try something like this:

const deleteHandler = async (faq) => {
    setLoadedFaq(loadedFaq.filter((f) => f._id !== faq._id)); 
  };
  • 1
    Sure you can. You just can't declare a new variable with the same name **and** expect it to keep the same value as its outer scoped couterpart. Within a new function its not actually *redeclaring* anything. It doesn't have any effect on the state value. – Brian Thompson May 21 '20 at 19:15
  • You are right. I phrased it wrongly. I should have said "You shouldn't redeclare it" – Harris Konstantourakis May 21 '20 at 19:17
1

A more concise solution would be to not use a temporary variable at all:

const deleteHandler = async (faq) => {
  setLoadedFaq(loadedFaq.filter((f) => f._id !== faq._id));
};

This avoids the shadowing issue caused by declaring a new const with the same name, and is more concise.

Here is an illustration of what caused the original issue:

const {useState} = React;

const Example = () => {
  const [value, setValue] = useState('test');
  
  const myFunction = () => {
    // value comes from the outer scope
    console.log(value);
  }  
  
  const myOtherFunction = () => {
    // value comes from new variable
    const value = 'new!';
    console.log(value);
    // notice it does not modify the state value
    // if you click Test 1 again
  }
  
  const myWrongFunction = () => {
    // value is undefined because we *will* declare it within inner scope
    // even though the outer variable is technically within scope, we cant use it anymore
    console.log(value);
    const value = 'new!';
    
    // value is from new variable
    console.log(value);
  }
   
   return (
    <div>
      <button onClick={() => myFunction()}>Test 1</button>
      <button onClick={() => myOtherFunction()}>Test 2</button>
      <button onClick={() => myWrongFunction()}>Test 3</button>
    </div>
   )
}

ReactDOM.render(<Example />, 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>
Brian Thompson
  • 13,263
  • 4
  • 23
  • 43
  • Ah, I see. Problem is that two of you have given me the exact same correct answer and I don't know who to mark as accepted? I am going to have to go on a technicality in that Brian seems to have correct a statement that Harris made. Sorry, I don't know how else to do it. Would accept both answers if I could! – user8463989 May 21 '20 at 19:15
  • @user8463989 I updated my answer with a working example of what caused the original problem. Hopefully that clears things up for the future instead of just getting a working solution for now. – Brian Thompson May 21 '20 at 19:24
  • Thanks Brian, I really appreciate the extra effort! – user8463989 May 21 '20 at 19:34