coreui-react icon indicating copy to clipboard operation
coreui-react copied to clipboard

[React] CMultiSelect: if options change, the element is not updated

Open lucagalbu opened this issue 3 years ago • 4 comments

  • Operating system and version: Windows 10, MacOS Catalina
  • Browser and version: Chrome, Firefox

If the prop options change, the component is not redrawn.

Test case

Here is a simple app that has a button and a component Component with a CMultiSelect. When the button is pressed, it randomly selects 3 universities from an array of 10 names, and renders the CMultiSelect in Component with these 3 random names.

However, when the button is pressed, the component Component is redrawn, but CMultiSelect is not.

App.tsx

import React from "react";
import Component from "./Component";

const data = [
  "Garrett College",
  "Cecil College",
  "City Colleges of Chicago-​Malcolm X College",
  "University of Missouri - Saint Louis",
  "Kilgore College",
  "Rainy River Community College"
];

function App() {
  const [uni, setUni] = React.useState<any[]>([]);

  const fetchUniversities = function () {
    const sliced = [];
    for (let i = 0; i < 3; i++) {
      let rndIndex = Math.random() * (data.length - 1);
      rndIndex = Math.round(rndIndex);
      sliced.push({
        text: data[rndIndex],
        value: i
      });
    }
    setUni(sliced);
  };

  return (
    <>
      <div className="App">
        <button onClick={() => fetchUniversities()}>Update values</button>
      </div>
      <div>
        <Component values={uni} />
      </div>
    </>
  );
}

export default App;

Component.tsx

import React from "react";
import { CMultiSelect } from "@coreui/react-pro";

const Component = (props: any) => {
  console.log(props.values);
  return <CMultiSelect options={props.values} />;
};

export default Component;

lucagalbu avatar Apr 04 '22 14:04 lucagalbu

The problem is in the code of the CMultiSelect.tsx:

This part

    useEffect(() => {
      const selected = _options && getSelectedOptions(_options);

      selected.sort((a: Option, b: Option) => {
        if (typeof a.order === "undefined") {
          return -1;
        }
        if (b.order && a.order > b.order) return 1;
        if (b.order && a.order < b.order) return -1;
        return 0;
      });
      setSelected(selected);
    }, [_options, options]);

is missing an effect to update the _options when the options change. Also the effect depends on options although the callback does not depend on options. So the correct code would be:

useEffect(() => {
      setOptions(options);
    }, [options]);

useEffect(() => {
  const selected = _options && getSelectedOptions(_options);

  selected.sort((a: Option, b: Option) => {
    if (typeof a.order === "undefined") {
      return -1;
    }
    if (b.order && a.order > b.order) return 1;
    if (b.order && a.order < b.order) return -1;
    return 0;
  });

  setSelected(selected);
}, [_options]);

lucagalbu avatar Apr 04 '22 14:04 lucagalbu

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

github-actions[bot] avatar Jun 04 '22 14:06 github-actions[bot]

Any news/hint on how to modify the source code of CMultiSelect.tsx @lucagalbu @mrholek? I've just stumbled upon the same issue...

MatteoBuffo avatar Jun 14 '22 13:06 MatteoBuffo

Will be fixed in the next release.

mrholek avatar Jul 06 '22 23:07 mrholek

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

github-actions[bot] avatar Sep 05 '22 14:09 github-actions[bot]