Skip to content

Instantly share code, notes, and snippets.

@lipemat
Created March 16, 2019 19:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lipemat/7360b96179fcfb7502f5359e4cb9569d to your computer and use it in GitHub Desktop.
Save lipemat/7360b96179fcfb7502f5359e4cb9569d to your computer and use it in GitHub Desktop.
React Column Aware Layout
import React, {useState, useRef, useMemo, useCallback, useEffect} from 'react';
import {hot} from 'react-hot-loader/root';
import {ITEMS} from "../globals/config";
import Item from "../components/team/Item";
import Slide_And_Scroll from "../components/transitions/Slide_And_Scroll";
import Current from "../components/team/Current";
import chunk from 'lodash/chunk';
import debounce from 'lodash/debounce';
const getCurrentFromHash = () => {
if ( window.location.hash ) {
return ITEMS.filter( item => '#' + item.slug === window.location.hash ).shift();
}
return null;
};
const getItemChunks = ( $columnCount ) => {
return chunk( ITEMS, $columnCount );
};
const getColumnCount = () => {
if ( document.body.clientWidth < 640 ) {
return 2;
}
if ( document.body.clientWidth < 768 ) {
return 3;
}
return 4;
};
export default hot( () => {
const [current, setCurrent] = useState( {
post: getCurrentFromHash(),
closed: false
} );
const [columns, setColumns] = useState( getColumnCount() );
const rows = useMemo( () => getItemChunks( columns ), [columns] );
const clickedRef = useRef( null );
// Recount the columns on resize.
useEffect( () => {
const cb = debounce( () => setColumns( getColumnCount() ), 500 );
window.addEventListener( 'resize', cb );
return () => {
window.removeEventListener( 'resize', cb );
}
}, [] );
const close = useCallback( () => {
const offset = $( clickedRef.current ).offset();
$( 'html, body' ).animate( {
scrollTop: offset.top,
scrollLeft: offset.left
} );
setCurrent( {...current, ...{closed: true}} );
}, [current] );
const open = useCallback( ( post ) => {
setCurrent( {
post: post,
closed: false
} );
}, [] );
return (
<div className="team-wrap">
{rows.map( ( posts, i ) => {
let currentInThisRow = false;
return (
<div className="row" key={'team-row-' + i}>
{posts.map( post => {
if ( post === current.post ) {
currentInThisRow = true;
return <Item key={post.id} ref={clickedRef} open={open} post={post} close={close}
active={!current.closed} columnCount={columns}/>
} else {
return <Item key={post.id} open={open} post={post} inactive={current.post !== null}
columnCount={columns}/>
}
} )}
{currentInThisRow &&
<Slide_And_Scroll clickedElement={clickedRef.current} closed={current.closed}>
<Current post={current.post} close={close}/>
</Slide_And_Scroll>}
</div>
)
} )}
</div>
);
} );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment