【问题标题】:useContext() react hook doesn't return the correct valueuseContext() 反应钩子没有返回正确的值
【发布时间】:2019-02-19 18:30:27
【问题描述】:
我将我的 Home 组件包装在以下布局中:
export const DataContext = React.createContext({});
const Layout: React.FunctionComponent = (props) => {
const data = {title: "abc", description: "def"};
return (
<DataContext.Provider value={data}>
{props.children}
</DataContext.Provider>
);
};
我想在我的 Home 组件中使用 useContext 挂钩,但它返回一个空对象:
const Home: React.FunctionComponent = () => {
const content = React.useContext(DataContext);
return (
<Layout>
// content data goes here
</Layout>
);
};
我怀疑这是因为我在包含上下文提供程序的布局包装器之外定义了上下文变量,所以它回退到我定义的上下文的默认值(一个空对象)。但是,即使我在布局提供程序中控制台记录 useContext 挂钩,它也会返回一个空对象:
const Home: React.FunctionComponent = () => {
const content = React.useContext(DataContext);
return (
<Layout>
{console.log(React.useContext(DataContext))}
</Layout>
);
};
知道为什么吗?
【问题讨论】:
标签:
javascript
reactjs
react-hooks
【解决方案1】:
useContext 将从树上最靠近它的Provider 获取value。您的 Layout 位于 Home 内部,这将使树中的 Provider 在其下方。
您可以将Home 设置为Layout 的子级,以使其正常工作。
示例
const DataContext = React.createContext({});
const Layout = props => {
const data = { title: "abc", description: "def" };
return (
<DataContext.Provider value={data}>{props.children}</DataContext.Provider>
);
};
const Home = () => {
const content = React.useContext(DataContext);
return <div>{JSON.stringify(content)}</div>;
};
function App() {
return (
<Layout>
<Home />
</Layout>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
【解决方案2】:
您认为 useContext 在 Layout 之外使用时提供空对象的假设确实是正确的。如果层次结构中没有Provider,则useContext返回提供给React.createContext的默认值
此外,您只能在功能组件的开头使用React hooks,而不能在渲染中使用。因此,如果您编写如下代码,您将能够正确记录上下文值
const Content: React.FunctionComponent = () => {
const content = React.useContext(DataContext);
console.log(content);
return (
<div>Content</div>
)
}
const Home: React.FunctionComponent = () => {
return (
<Layout>
<Content />
</Layout>
);
};
Working demo
【解决方案3】:
好吧,我也遇到了同样的问题,经过大量谷歌搜索后,我发现每当我们的页面刷新时,它都会将上下文值设置为默认值。
因此,如果您使用标签或类似的东西进行导航或刷新页面的东西,那么请使用 react-router-dom 中的标签或代替。
这对我有用。