` element, containing a `` for each key in the object.
+- **Note:** This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`.
+
+```jsx
+const MappedTable = ({ data, propertyNames }) => {
+ let filteredData = data.map(v =>
+ Object.keys(v)
+ .filter(k => propertyNames.includes(k))
+ .reduce((acc, key) => ((acc[key] = v[key]), acc), {})
+ );
+ return (
+
+
+
+ {propertyNames.map(val => (
+ | {val} |
+ ))}
+
+
+
+ {filteredData.map((val, i) => (
+
+ {propertyNames.map(p => (
+ | {val[p]} |
+ ))}
+
+ ))}
+
+
+ );
+};
+```
+
+```jsx
+const people = [
+ { name: 'John', surname: 'Smith', age: 42 },
+ { name: 'Adam', surname: 'Smith', gender: 'male' }
+];
+const propertyNames = ['name', 'surname', 'age'];
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+);
+```
diff --git a/react/snippets/modal.md b/react/snippets/modal.md
new file mode 100644
index 000000000..91dadb2c9
--- /dev/null
+++ b/react/snippets/modal.md
@@ -0,0 +1,157 @@
+---
+title: Modal dialog
+type: snippet
+tags: [components,effect]
+cover: yellow-white-mug-2
+dateModified: 2021-10-13T19:29:39+02:00
+---
+
+Renders a Modal component, controllable through events.
+
+- Define a `keydownHandler` that handles all keyboard events and calls `onClose` when the `Esc` key is pressed.
+- Use the `useEffect()` hook to add or remove the `keydown` event listener to the `Document`, calling `keydownHandler` for every event.
+- Add a styled `` element that acts as a close button, calling `onClose` when clicked.
+- Use the `isVisible` prop passed down from the parent to determine if the modal should be displayed or not.
+- To use the component, import `Modal` only once and then display it by passing a boolean value to the `isVisible` attribute.
+
+```css
+.modal {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 100%;
+ z-index: 9999;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: rgba(0, 0, 0, 0.25);
+ animation-name: appear;
+ animation-duration: 300ms;
+}
+
+.modal-dialog {
+ width: 100%;
+ max-width: 550px;
+ background: white;
+ position: relative;
+ margin: 0 20px;
+ max-height: calc(100vh - 40px);
+ text-align: left;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
+ -webkit-animation-name: animatetop;
+ -webkit-animation-duration: 0.4s;
+ animation-name: slide-in;
+ animation-duration: 0.5s;
+}
+
+.modal-header,
+.modal-footer {
+ display: flex;
+ align-items: center;
+ padding: 1rem;
+}
+
+.modal-header {
+ border-bottom: 1px solid #dbdbdb;
+ justify-content: space-between;
+}
+
+.modal-footer {
+ border-top: 1px solid #dbdbdb;
+ justify-content: flex-end;
+}
+
+.modal-close {
+ cursor: pointer;
+ padding: 1rem;
+ margin: -1rem -1rem -1rem auto;
+}
+
+.modal-body {
+ overflow: auto;
+}
+
+.modal-content {
+ padding: 1rem;
+}
+
+@keyframes appear {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes slide-in {
+ from {
+ transform: translateY(-150px);
+ }
+ to {
+ transform: translateY(0);
+ }
+}
+```
+
+```jsx
+const Modal = ({ isVisible = false, title, content, footer, onClose }) => {
+ const keydownHandler = ({ key }) => {
+ switch (key) {
+ case 'Escape':
+ onClose();
+ break;
+ default:
+ }
+ };
+
+ React.useEffect(() => {
+ document.addEventListener('keydown', keydownHandler);
+ return () => document.removeEventListener('keydown', keydownHandler);
+ });
+
+ return !isVisible ? null : (
+
+ e.stopPropagation()}>
+
+ {title}
+
+ ×
+
+
+
+ {footer && {footer} }
+
+
+ );
+};
+```
+
+```jsx
+const App = () => {
+ const [isModal, setModal] = React.useState(false);
+ return (
+ <>
+
+ Add your content here}
+ footer={}
+ onClose={() => setModal(false)}
+ />
+ >
+ );
+};
+
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+);
+```
diff --git a/react/snippets/multiselect-checkbox.md b/react/snippets/multiselect-checkbox.md
new file mode 100644
index 000000000..08dc75247
--- /dev/null
+++ b/react/snippets/multiselect-checkbox.md
@@ -0,0 +1,58 @@
+---
+title: Stateful checkbox with multiple selection
+type: snippet
+tags: [components,input,state,array]
+cover: violin
+dateModified: 2021-10-13T19:29:39+02:00
+---
+
+Renders a checkbox list that uses a callback function to pass its selected value/values to the parent component.
+
+- Use the `useState()` hook to create the `data` state variable and use the `options` prop to initialize its value.
+- Create a `toggle` function that uses the spread operator (`...`) and `Array.prototype.splice()` to update the `data` state variable and call the `onChange` callback with any `checked` options.
+- Use `Array.prototype.map()` to map the `data` state variable to individual `` elements. Wrap each one in a ` |