@itwin/unified-selection-react
Version:
React components for making use of `@itwin/unified-selection` package in React applications more straightforward
70 lines (55 loc) • 3.54 kB
Markdown
# for license terms and full copyright notice.
The ` /unified-selection-react` package provides React APIs for conveniently using the [ /unified-selection](https://github.com/iTwin/presentation/blob/master/packages/unified-selection/README.md)
package in React applications and components.
## React context for unified selection
There are two ways to pass data to React components - through props or context. While the former is preferred, the latter [also has its uses](https://react.dev/reference/react/useContext#passing-data-deeply-into-the-tree). One caveat about React contexts is that context provider and context consumer MUST use the exact same context object. This package delivers a unified selection React context exactly for this reason - it allows context providers and consumers, which may come from different packages and have no direct dependency on each other, to share the same selection storage.
Example usage:
<!-- [[include: [Presentation.UnifiedSelectionReact.Context.Imports, Presentation.UnifiedSelectionReact.Context.Example], tsx]] -->
<!-- BEGIN EXTRACTION -->
```tsx
import { createStorage, Selectables, SelectionStorage } from "@itwin/unified-selection";
import { UnifiedSelectionContextProvider, useUnifiedSelectionContext } from "@itwin/unified-selection-react";
/** A top-level component that creates the selection storage and sets up the context provider for all inner components to use */
function App() {
const [selectionStorage] = useState(() => createStorage());
const idCounter = useRef(0);
return (
<UnifiedSelectionContextProvider storage={selectionStorage}>
<button
onClick={() =>
selectionStorage.addToSelection({
imodelKey,
source: "my-button",
selectables: [{ className: "BisCore.Element", id: `0x${++idCounter.current}` }],
})
}
>
Select an element
</button>
<MyComponent />
</UnifiedSelectionContextProvider>
);
}
/** An internal component that takes unified selection storage from context and prints the number of selected elements */
function MyComponent() {
const selectionContext = useUnifiedSelectionContext();
if (!selectionContext) {
throw new Error("Unified selection context is not available");
}
function getSelectedElementsCount(storage: SelectionStorage) {
return Selectables.size(storage.getSelection({ imodelKey }));
}
const [selectedElementsCount, setSelectedElementsCount] = useState(() => getSelectedElementsCount(selectionContext.storage));
useEffect(() => {
return selectionContext.storage.selectionChangeEvent.addListener(() => {
setSelectedElementsCount(getSelectedElementsCount(selectionContext.storage));
});
}, [selectionContext.storage]);
return `Number of selected elements: ${selectedElementsCount}`;
}
```
<!-- END EXTRACTION -->
For the above to work, both - context provider and consumer - must use the same dependency of this package (see [symptoms here](https://react.dev/reference/react/useContext#troubleshooting) for when they don't do that). One way to ensure this is to have the following set up:
- Context provider should have a direct dependency on this, as well as the ` /unified-selection`, packages.
- Context consumer should have a peer dependency on this package. This way, the consumer will use the same version of the context as the provider.
/unified-selection-react
Copyright © Bentley Systems, Incorporated. All rights reserved. See LICENSE.md