我已经创建了一个高阶组件,该组件应该为我的组件添加一些其他功能。但是,当我在此组件中使用React Hook时,我会收到以下ESLINT警告。
React Hook" React.useeffect"无法在回调中调用。反应 必须在React功能组件或自定义React中调用挂钩 钩功能。(React-Hooks/hooks of Hooks(
我为什么要警告?在事件中使用钩子是否被认为是不好的做法?
最小示例:
const Hello = props => <p>Greetings {props.name}</p>;
const Wrapper = Component => props => {
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
};
export default Wrapper(Hello)
codesandbox:https://codesandbox.io/s/proud-tree-5kscc
转换
props => {
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
};
在您的事件内到一个功能(hoks/hooks of hooks thffr thf抛出您在箭头函数中使用时显示的警告(
(所以,将其更改为
const Wrapper = Component =>
function Comp(props) {
React.useEffect(() => {
console.log("useEffect");
}, []);
return <Component {...props} />;
};
,效果被触发。
这是Codesandbox上的一个工作示例
官方react Hooks文档说:
不要从常规JavaScript函数中调用钩子。相反,您可以:
✅来自React功能组件的调用钩子。
✅从自定义钩中调用钩子。
正如@asafaviv所说,您应该将房屋重构为自定义钩子,以避免违反钩子的规则。
原因是在常见问题中描述:
如何与组件进行辅助挂钩调用?
React跟踪当前渲染组件。多亏了钩子的规则,我们知道挂钩仅是从React组件(或自定义钩子(调用的,也仅从React组件中调用(。
有一个与每个组件关联的"内存单元"的内部列表。它们只是JavaScript对象,我们可以在其中放置一些数据。当您调用usestate((之类的挂钩时,它会读取当前的单元格(或在第一个渲染期间初始化它(,然后将指针移至下一个指针。这就是多个usestate((调用每个都能获得独立本地状态的方式。
您可以在功能组件中或自定义钩中使用React钩子。重写您的事件:
const Hello = props => <p>Greetings {props.name}</p>;
const HookDoSomething = () => {
React.useEffect(() => {
// Do something here
}, []);
}
const Wrapper = Component => props => {
HookDoSomething()
return <Component {...props} />;
};
export default Wrapper(Hello)
在您定义了HOC的文件中,只需将以下内容添加到文件顶部:
/* eslint-disable react-hooks/rules-of-hooks */
钩子和高阶组件是两个完全不同的东西。任何说可以由钩子替换的人都从来没有真正写过事事或玩语义游戏。
当我编写HOC时,我通常必须禁用rules-of-hooks
ESLINT规则,因为该规则太严格了,它认为是钩子或组件。HOC比钩子更类似于组件,但该规则无法识别。
Short Answer
:您只需要将回调更改为pascalcase函数或使用函数即可。这是因为Eslint规则具有一些您需要遵循的启发式,以便它检测组件。
您需要将代码更改为
const Wrapper = Component => {
return function WithWrapper(props){
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
}
}
只需将名称更改为较低情况喜欢:
withWrrapperHOC = Comp => props => {
useEffect(()=>{
//...
},[])
return (<Comp {...props}>)
}