是否可以在 React 呈现其组件之前激活 scrollTo?
Is it possible to activate a scrollTo before React renders its components?
在我的 React 应用程序中,我有一个 TextHistory 组件,它在一个小包装器中显示给定文本的保存历史记录。 React Router 允许我单独访问每个版本 (localhost:3000/view/[textId]/[versionId])。在每次版本切换时,React Router 都会重新呈现整个页面,包括 TextHistory,这会将其滚动位置重置为其包装器的顶部。
为了将位置设置回上一页,我在离开所述页面之前将滚动位置保存在 Redux 中。然后,在新的 TextHistory 渲染中,我只是读取保存的位置并设置 TextHistory 组件的 scrollTop(与 scrollTo() 的结果相同) .至此,一切都完美了。
我的问题是 React 有时间在考虑 scrollTo 之前显示原始未滚动的组件,导致组件在屏幕上轻微闪烁。有没有一种方法可以强制在 React 实际渲染组件之前发生滚动?
const TextHistory = props => {
useSelector(state => state.texts.activeTextHistory.textId)
const historyDataRef = useRef(null);
// Component updates
//------------------
useEffect(() => {
if (historyDataRef.current)
historyDataRef.current.scrollTop = store.getState().texts.activeTextHistory.scrollPos;
});
// Handles
//--------
function handleLeave(e) {
store.dispatch(setActiveTextHistory({ ...store.getState().texts.activeTextHistory, scrollPos: e.target.parentNode.parentNode.scrollTop }));
}
// Rendering
//----------
let versions = [];
store.getState().texts.activeTextHistory.history.map((entry, index) => {
let date = MySQLTimestampToDate(entry.creationDate);
let link = `/view/${props.textId}/${entry.version}`;
versions.push(
<span key={index}>
<EpistoLadsLink to={link} onLeave={handleLeave}>
<FormattedMessage id="textViewer.version" values={{ version: entry.version }} />
</EpistoLadsLink>
<FormattedMessage id="textViewer.creationData" values={{ date: date.toLocaleDateString("fr-FR"), time: date.toLocaleTimeString("fr-FR") }} />
<br />
</span>
);
});
//-----
return (
<div id="textHistory">
{versions.length > 0 &&
<Fragment>
<FormattedMessage id="history.title"/>
<div id="historyData" ref={historyDataRef}>{versions}</div>
</Fragment>
}
</div>
);
};
有一个名为 useLayoutEffect
的 React Hooks api,我相信它可以帮助你。
该挂钩类似于 useEffect
挂钩,但不同之处在于 useLayoutEffect
内安排的更新将在浏览器有机会绘制之前同步刷新。
这样使用它 -
useLayoutEffect(() => {
if (historyDataRef.current)
historyDataRef.current.scrollTop = store.getState().texts.activeTextHistory.scrollPos;
});
在我的 React 应用程序中,我有一个 TextHistory 组件,它在一个小包装器中显示给定文本的保存历史记录。 React Router 允许我单独访问每个版本 (localhost:3000/view/[textId]/[versionId])。在每次版本切换时,React Router 都会重新呈现整个页面,包括 TextHistory,这会将其滚动位置重置为其包装器的顶部。
为了将位置设置回上一页,我在离开所述页面之前将滚动位置保存在 Redux 中。然后,在新的 TextHistory 渲染中,我只是读取保存的位置并设置 TextHistory 组件的 scrollTop(与 scrollTo() 的结果相同) .至此,一切都完美了。
我的问题是 React 有时间在考虑 scrollTo 之前显示原始未滚动的组件,导致组件在屏幕上轻微闪烁。有没有一种方法可以强制在 React 实际渲染组件之前发生滚动?
const TextHistory = props => {
useSelector(state => state.texts.activeTextHistory.textId)
const historyDataRef = useRef(null);
// Component updates
//------------------
useEffect(() => {
if (historyDataRef.current)
historyDataRef.current.scrollTop = store.getState().texts.activeTextHistory.scrollPos;
});
// Handles
//--------
function handleLeave(e) {
store.dispatch(setActiveTextHistory({ ...store.getState().texts.activeTextHistory, scrollPos: e.target.parentNode.parentNode.scrollTop }));
}
// Rendering
//----------
let versions = [];
store.getState().texts.activeTextHistory.history.map((entry, index) => {
let date = MySQLTimestampToDate(entry.creationDate);
let link = `/view/${props.textId}/${entry.version}`;
versions.push(
<span key={index}>
<EpistoLadsLink to={link} onLeave={handleLeave}>
<FormattedMessage id="textViewer.version" values={{ version: entry.version }} />
</EpistoLadsLink>
<FormattedMessage id="textViewer.creationData" values={{ date: date.toLocaleDateString("fr-FR"), time: date.toLocaleTimeString("fr-FR") }} />
<br />
</span>
);
});
//-----
return (
<div id="textHistory">
{versions.length > 0 &&
<Fragment>
<FormattedMessage id="history.title"/>
<div id="historyData" ref={historyDataRef}>{versions}</div>
</Fragment>
}
</div>
);
};
有一个名为 useLayoutEffect
的 React Hooks api,我相信它可以帮助你。
该挂钩类似于 useEffect
挂钩,但不同之处在于 useLayoutEffect
内安排的更新将在浏览器有机会绘制之前同步刷新。
这样使用它 -
useLayoutEffect(() => {
if (historyDataRef.current)
historyDataRef.current.scrollTop = store.getState().texts.activeTextHistory.scrollPos;
});