code: "import { useState, useEffect } from 'react';\r\n\r\nfunction App() {\r\n const columnCount = useMedia(\r\n \/\/ Media queries\r\n ['(min-width: 1500px)', '(min-width: 1000px)', '(min-width: 600px)'],\r\n \/\/ Column counts (relates to above media queries by array index)\r\n [5, 4, 3],\r\n \/\/ Default column count\r\n 2\r\n );\r\n\r\n \/\/ Create array of column heights (start at 0)\r\n let columnHeights = new Array(columnCount).fill(0);\r\n\r\n \/\/ Create array of arrays that will hold each column's items\r\n let columns = new Array(columnCount).fill().map(() => []);\r\n\r\n data.forEach(item => {\r\n \/\/ Get index of shortest column\r\n const shortColumnIndex = columnHeights.indexOf(Math.min(...columnHeights));\r\n \/\/ Add item\r\n columns[shortColumnIndex].push(item);\r\n \/\/ Update height\r\n columnHeights[shortColumnIndex] += item.height;\r\n });\r\n\r\n \/\/ Render columns and items\r\n return (\r\n <div className=\"App\">\r\n <div className=\"columns is-mobile\">\r\n {columns.map(column => (\r\n <div className=\"column\">\r\n {column.map(item => (\r\n <div\r\n className=\"image-container\"\r\n style={{\r\n \/\/ Size image container to aspect ratio of image\r\n paddingTop: (item.height \/ item.width) * 100 + '%'\r\n }}\r\n >\r\n <img src={item.image} alt=\"\" \/>\r\n <\/div>\r\n ))}\r\n <\/div>\r\n ))}\r\n <\/div>\r\n <\/div>\r\n );\r\n}\r\n\r\n\/\/ Hook\r\nfunction useMedia(queries, values, defaultValue) {\r\n \/\/ Array containing a media query list for each query\r\n const mediaQueryLists = queries.map(q => window.matchMedia(q));\r\n\r\n \/\/ Function that gets value based on matching media query\r\n const getValue = () => {\r\n \/\/ Get index of first media query that matches\r\n const index = mediaQueryLists.findIndex(mql => mql.matches);\r\n \/\/ Return related value or defaultValue if none\r\n return typeof values[index] !== 'undefined' ? values[index] : defaultValue;\r\n };\r\n\r\n \/\/ State and setter for matched value\r\n const [value, setValue] = useState(getValue);\r\n\r\n useEffect(\r\n () => {\r\n \/\/ Event listener callback\r\n \/\/ Note: By defining getValue outside of useEffect we ensure that it has ...\r\n \/\/ ... current values of hook args (as this hook callback is created once on mount).\r\n const handler = () => setValue(getValue);\r\n \/\/ Set a listener for each media query with above handler as callback.\r\n mediaQueryLists.forEach(mql => mql.addListener(handler));\r\n \/\/ Remove listeners on cleanup\r\n return () => mediaQueryLists.forEach(mql => mql.removeListener(handler));\r\n },\r\n [] \/\/ Empty array ensures effect is only run on mount and unmount\r\n );\r\n\r\n return value;\r\n}"
0 commit comments