【发布时间】:2020-08-27 01:59:18
【问题描述】:
我有一个问题,我有一个简单的 React.Context,它在所有组件安装之后 填充。问题是因为它发生在挂载之后,nextjs 在初始渲染时看不到这个数据,所以有明显的闪烁。
这是设置上下文的简单组件:
export const SetTableOfContents = (props: { item: TableOfContentsItem }) => {
const toc = useContext(TableOfContentsContext);
useEffect(() => {
// Updates the React.Context after the component mount
// (since useEffects run after mount)
toc.setItem(props.item);
}, [props.item, toc]);
return null;
};
这里是 React.Context。它使用 React 状态来存储 TOC 项。
export const TableOfContentsProvider = (props: {
children?: React.ReactNode;
}) => {
const [items, setItems] = useState<TableOfContents["items"]>([]);
const value = useMemo(() => {
return {
items,
setItem(item: TableOfContentsItem) {
setItems((items) => items.concat(item));
},
};
}, [items]);
return (
<TableOfContentsContext.Provider value={value}>
{props.children}
</TableOfContentsContext.Provider>
);
};
目前,无法设置 React.Context before 挂载,因为 React 会发出警告---无法在渲染时更新状态。
我能想到的唯一解决方法是使用 除了 React.state 之外的其他东西作为 React.Context 状态——这样组件就可以随时更新它。但是这种方法的问题是上下文消费者将不再知道项目发生了变化(因为更新存在于 React 生命周期之外)!
那么如何让初始的 React.Context 进入初始的 SSR 渲染呢?
const items = [];
export const TableOfContentsProvider = (props: {
children?: React.ReactNode;
}) => {
const value = useMemo(() => {
return {
items,
setItem(item: TableOfContentsItem) {
items[item.index] = item;
},
};
// this dep never changes.
// when you call this function, values never change
}, [items]);
return (
<TableOfContentsContext.Provider value={value}>
{props.children}
</TableOfContentsContext.Provider>
);
};
【问题讨论】:
-
在
getInitialProps做你想做的事的好地方 -
你无权访问那里的上下文@EranGoldin
-
对。那这个怎么样? stackoverflow.com/questions/54709299/…
-
虽然不是很感谢@EranGoldin。发表了我最终做了什么
标签: next.js react-context