Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Helper class for react hooks, context won't render after new value is return from helper

I have hook component with a useContext and useState, both works as intended. I also have a useEffect to trigger on any change of my state "selectedItems". I also have a utility class with some simple logic that will return a modified array. It looks like this:

    useEffect(() => {
    console.log(selectedItems);
}, [selectedItems])

and

const ItemBox = ({item}) => {
const [selectedItems, setSelectedItems] = useContext(SelectedContext);  return (
  <div onClick={() => setSelectedItems(InventoryUtil.selectOrDeselectItem(item, selectedItems))} className="itemBox">
  </div>)};

And helper/util function looks like this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    selectOrDeselectItem(item, selectedItems) {
    if (selectedItems.includes(item)) {
        selectedItems.splice(selectedItems.indexOf(item), 1);
        return selectedItems;
    }
    selectedItems.push(item);
    return selectedItems;
}

And the logic works when I’m logging it to the console and everything looks fine, but my useEffect is not triggering when selectedItems is changing via my helper function. It only triggers when i feed a direct value into it, but everything that goes via my util/helper class won’t trigger it.

So my question is why and what is the best practice when it comes to creating helper/utils logic functions with react hooks that simply takes in some value and return a modified array.

>Solution :

This is because you are returning the reference to the same object and React cannot detect it as an updated state variable.
Also the best practice is to use functional setState pattern when the next value depends on the previous value.

You can use this, it solves both:

onClick={() => setSelectedItems((selectedItems) => InventoryUtil.selectOrDeselectItem(item, [...selectedItems])))}

Note that the best practice would be to not modify any incoming components so instead of destructuring while passing, you could do it at the top of your function:

selectOrDeselectItem(item, initSelectedItems) {
const selectedItems = [...initSelectedItems];
    if (selectedItems.includes(item)) {
        selectedItems.splice(selectedItems.indexOf(item), 1);
        return selectedItems;
    }
    selectedItems.push(item);
    return selectedItems;
}

and keep this like:

onClick={() => setSelectedItems((selectedItems) => InventoryUtil.selectOrDeselectItem(item, selectedItems)))}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading