-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 \/\/ State update function\r\n const match = () => {\r\n \/\/ Get first media query that matches\r\n const query = queries.findIndex(q => matchMedia(q).matches);\r\n \/\/ Return related value or defaultValue if none\r\n return values[query] || defaultValue;\r\n };\r\n \r\n \/\/ State and setter for current value\r\n const [value, set] = useState(match);\r\n\r\n useEffect(() => {\r\n \/\/ Update state on window resize\r\n \/\/ Usage of match function defined outside of useEffect ...\r\n \/\/ ... ensures that it has current values of arguments.\r\n const handler = () => set(match);\r\n window.addEventListener('resize', handler);\r\n \/\/ Remove event listener on cleanup\r\n return () => window.removeEventListener('resize', handler);\r\n }, []); \/\/ Empty array ensures effect is only run on mount and unmount\r\n\r\n return value;\r\n}\r\n"
0 commit comments