preact/hooks#useLayoutEffect JavaScript Examples
The following examples show how to use
preact/hooks#useLayoutEffect.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: CodePanel.js From v8-deopt-viewer with MIT License | 5 votes |
/**
* @typedef CodePanelProps
* @property {import("../").FileV8DeoptInfoWithSources} fileDeoptInfo
* @property {number} fileId
* @property {import('./CodeSettings').CodeSettingsState} settings
* @param {CodePanelProps} props
*/
export function CodePanel({ fileDeoptInfo, fileId, settings }) {
if (fileDeoptInfo.srcError) {
return <CodeError srcError={fileDeoptInfo.srcError} />;
} else if (!fileDeoptInfo.src) {
return <CodeError srcError="No sources for the file were found." />;
}
const lang = determineLanguage(fileDeoptInfo.srcPath);
const state = useAppState();
const selectedLine = state.selectedPosition?.line;
/**
* @typedef {Map<string, import('../utils/deoptMarkers').Marker>} MarkerMap
* @type {[MarkerMap, import('preact/hooks').StateUpdater<MarkerMap>]}
*/
const [markers, setMarkers] = useState(null);
/** @type {import('preact').RefObject<HTMLElement>} */
const codeRef = useRef(null);
useLayoutEffect(() => {
// Saved the new markers so we can select them when CodePanelContext changes
const markers = addDeoptMarkers(codeRef.current, fileId, fileDeoptInfo);
setMarkers(new Map(markers.map((marker) => [marker.id, marker])));
}, [fileId, fileDeoptInfo]);
useEffect(() => {
if (state.prevSelectedEntry) {
markers
.get(getMarkerId(state.prevSelectedEntry))
?.classList.remove(active);
}
/** @type {ScrollIntoViewOptions} */
const scrollIntoViewOpts = { block: "center", behavior: "smooth" };
if (state.selectedEntry) {
const target = markers.get(getMarkerId(state.selectedEntry));
target.classList.add(active);
// TODO: Why doesn't the smooth behavior always work? It seems that only
// the first or last call to scrollIntoView with behavior smooth works?
target.scrollIntoView(scrollIntoViewOpts);
} else if (state.selectedPosition) {
const lineSelector = `.line-numbers-rows > span:nth-child(${state.selectedPosition.line})`;
document.querySelector(lineSelector)?.scrollIntoView(scrollIntoViewOpts);
}
// TODO: Figure out how to scroll line number into view when
// selectedPosition is set but selectedMarkerId is not
}, [state]);
return (
<div
class={[
codePanel,
(settings.showLowSevs && showLowSevsClass) || null,
].join(" ")}
>
<PrismCode
src={fileDeoptInfo.src}
lang={lang}
class={(!settings.hideLineNums && "line-numbers") || null}
ref={codeRef}
>
<LineNumbers selectedLine={selectedLine} contents={fileDeoptInfo.src} />
</PrismCode>
</div>
);
}
Example #2
Source File: graph.js From rctf with BSD 3-Clause "New" or "Revised" License | 4 votes |
function Graph ({ graphData, classes }) {
const svgRef = useRef(null)
const [width, setWidth] = useState(window.innerWidth)
const updateWidth = useCallback(() => {
if (svgRef.current === null) return
setWidth(svgRef.current.getBoundingClientRect().width)
}, [])
const [tooltipData, setTooltipData] = useState({
x: 0,
y: 0,
content: ''
})
useLayoutEffect(() => {
updateWidth()
}, [updateWidth])
useEffect(() => {
function handleResize () {
updateWidth()
}
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [updateWidth])
const { polylines, labels } = useMemo(() => {
if (!graphData || graphData.length === 0) {
return {
polylines: [],
labels: []
}
}
const minX = config.startTime
const maxX = Math.min(Date.now(), config.endTime)
let maxY = 0
graphData.graph.forEach((user) => {
user.points.forEach((point) => {
if (point.score > maxY) {
maxY = point.score
}
})
})
const labels = getXLabels({ minX, maxX, width })
const polylines = graphData.graph.map((user) => pointsToPolyline({
points: user.points,
id: user.id,
name: user.name,
currentScore: user.points[0].score,
maxX,
minX,
maxY,
width
}))
return { polylines, labels }
}, [graphData, width])
const handleTooltipIn = useCallback((content) => () => {
setTooltipData(d => ({
...d,
content
}))
}, [])
const handleTooltipMove = useCallback((evt) => {
setTooltipData(d => ({
...d,
x: evt.clientX,
y: evt.clientY
}))
}, [])
const handleTooltipOut = useCallback(() => {
setTooltipData(d => ({
...d,
content: ''
}))
}, [])
if (graphData === null) {
return null
}
return (
<div class={`frame ${classes.root}`}>
<div class='frame__body'>
<svg ref={svgRef} viewBox={`${-stroke - axis} ${-stroke} ${width + stroke * 2 + axis} ${height + stroke * 2 + axis + axisGap}`}>
<Fragment>
{polylines.map(({ points, color, name, currentScore }, i) => (
<GraphLine
key={i}
stroke={color}
points={points}
name={name}
currentScore={currentScore}
onMouseMove={handleTooltipMove}
onMouseOut={handleTooltipOut}
onTooltipIn={handleTooltipIn}
/>
))}
</Fragment>
<Fragment>
{labels.map((label, i) => (
<text x={label.x} y={height + axis + axisGap} key={i} fill='#fff'>{label.label}</text>
))}
</Fragment>
<line
x1={-axisGap}
y1={height + axisGap}
x2={width}
y2={height + axisGap}
stroke='var(--cirrus-bg)'
stroke-linecap='round'
stroke-width={stroke}
/>
<line
x1={-axisGap}
y1='0'
x2={-axisGap}
y2={height + axisGap}
stroke='var(--cirrus-bg)'
stroke-linecap='round'
stroke-width={stroke}
/>
</svg>
</div>
{tooltipData.content && (
<div
class={classes.tooltip}
style={{
transform: `translate(${tooltipData.x}px, ${tooltipData.y}px)`
}}
>
{tooltipData.content}
</div>
)}
</div>
)
}