React MultiSelect - how to manage checked items externally

Posted by: jschnurer on 29 April 2024, 5:45 am EST

    • Post Options:
    • Link

    Posted 29 April 2024, 5:45 am EST

    I have a React app and am trying to use the Wijmo MultiSelect component. The list of items that are checked is stored externally from my component (in Redux).

    I am trying to encapsulate the Wijmo component in my own custom component and then expose certain props. One of the props is the list of items and another is the “onChange” even for when the user changes which item(s) are checked.

    When I attempt to do this, the Wijmo component infinitely calls the onChange event resulting in a max-depth recursion error from React.

    How can I accomplish this without Wijmo crashing React?

    Here is a live example of my issue:

    https://stackblitz.com/edit/react-7pxxyv?file=index.js,ComboBox.js,index.html

  • Posted 30 April 2024, 3:24 pm EST

    Hi,

    This issue happened because a useState variable is used as an itemsSource for the MultiSelect, which is updated when checked items are changed, which in turn re-renders the MultiSelect component as it is used as its itemsSource, which then triggers the ‘checkedItemsChanged’ event again as an item is to be selected after the re-render, and the loop continues that causes this issue. To avoid this issue, you’ll need to keep a separate copy of the same object which will be used as an itemsSource for the MultiSelect. To implement this, you can handle the ‘initialized’ event of the MultiSelect to assign an itemsSource instead of directly setting its ‘itemsSource’ property in the component markup, like this -

    function initControl(s) {
        s.itemsSource = [...props.items];
      }
    
      return (
        <MultiSelect
          ref={multiSel}
          dropDownCssClass={props.className}
          initialized={initControl}
          placeholder={props.placeholder ?? 'Select'}
          headerFormat={props.headerFormat ?? '{count:n0} items'}
          displayMemberPath="text"
          checkedMemberPath="isSelected"
          selectedValuePath="id"
          showSelectAllCheckbox={props.allowSelectAll ?? true}
          showFilterInput={props.allowFilter ?? true}
          checkedItemsChanged={(s) => {
            props.onChange(s.checkedItems);
          }}
        />
      );

    Please refer to the following updated sample for the same - https://stackblitz.com/edit/react-vfav9s?file=ComboBox.js

    Regards

  • Posted 1 May 2024, 12:03 am EST

    Hello,

    It is my understanding that the initialized event only runs when the component first renders and then never again. If something outside of this component updates my data source, for example to change the list of items or to mark some as checked or not checked, how would I update the MultiSelect component to let it know the data source has changed?

    Thanks.

  • Posted 1 May 2024, 11:48 pm EST

    Hi,

    One alternate way to get around this issue would be by updating the use state variable using a custom function, which will update the data in existing items/objects instead of replacing them with new items/objects. Please refer to the following updated sample for the same - https://stackblitz.com/edit/react-cjte37?file=ComboBox.js

    Refer to lines 72-80 in index.js file.

    Please note that, we have used the ‘useEvent’ hook in the ‘checkedItemsChanged’ event handler of the MultiSelect, this is necessary to get the updated value of the useState variables inside any event handler functions of Wijmo controls in React, as by default only the initial state of the useState variable is maintained in event handlers of any Wijmo control, to avoid unnecessary rendering.

    Regards

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels