我正在努力掌握React中新的useContext
函数。在无状态功能组件中非常有效。例如:
import React from 'react';
import LocaleContext from '../LocaleContext';
const Link = ({ text, url }) => {
const locale = useContext(LocaleContext);
return (
<a href={`/${locale}/${url}`}>
{text}
</a>
);
};
export default Link;
我也想在有状态组件甚至非React函数中使用useContext
,但是当我这样做时,出现以下错误:
Hooks can only be called inside the body of a function component.
该消息似乎很容易理解,但这是真的吗?我只能在无状态功能组件中使用它吗?如果是这样,对我来说似乎毫无意义,因为使用简单的HOC或传统方法超级简单:
<Locale Consumer>
{locale => (
...
)}
</LocaleConsumer>
那么这里有什么呢?我的项目中有每个软件包的最新版本。不确定是否重要,但是我正在这里开发NextJS网站。
答案 0 :(得分:4)
问题是错误所指示的内容。 React钩子在类组件中不可用。由于类组件和功能组件之间存在差异,因此挂钩不能与前者一起使用。
正如the documentation所说,
钩子使您无需类即可使用React的更多功能。从概念上讲,React组件始终更接近功能。钩子包含功能,但不影响React的实践精神。钩子可以访问命令式逃生舱门,并且不需要学习复杂的功能或反应性编程技术。
挂钩应该解决特定于类组件的常见用例,而这些类以前是无法单独使用无状态功能组件实现的。自从React 16.8起,功能组件就不是无状态的,它们被允许具有状态并触发自己的更新。
提供程序更新时,此挂钩将触发使用最新上下文值的重新呈现。
由于功能组件和类组件之间的差异,在类组件中会造成混乱。每次渲染组件时都会调用组件函数:
const Foo = props => {
const context = useContext(Context);
// use context
}
除了render
函数之外,类组件中没有其他位置会表现相同的行为。而且,如果特定于生命周期的任务转到render
函数,则意味着类是错误的选择,并且需要将类组件重构为函数。
类组件中与useContext
相对的是contextType
,目前仅限于单个上下文。
答案 1 :(得分:2)
如果您真的想使用类(我实际上来自Angular并且仍然喜欢使用类),则可以这样轻松地解决:
class ComponentImpl extends React.Component<any> {
constructor(props?) {
super(props);
}
render() {
return (
<div>
CounterButton: <button onClick={() => {this.props.appContext.setCount(this.props.appContext.count + 5)}}>App Counter + 5</button>
</div>
)
}
}
export function Component() {
let appContext = useContext(AppContext);
return <ComponentImpl appContext={appContext}></ComponentImpl>
};
您只需使用它:<Component></Component>
答案 2 :(得分:0)
useContext
是一个钩子,它使用上下文,并且只能在功能组件中使用。
如果您想在类组件中使用上下文,则需要查看其他方法,例如Consumer Component,official docs for this here