我创建了一个更高阶的组件,该组件应该为我的组件添加一些其他功能。但是,当我在此组件中使用react钩子时,会收到以下eslint警告。
反应挂钩“ React.useEffect”不能在回调内调用。反应 挂钩必须在React函数组件或自定义React中调用 挂钩功能。 (反应钩/钩规则)
我为什么收到此警告?在HoC中使用钩子是否被认为是不好的做法?
最小示例:
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
答案 0 :(得分:3)
official React Hooks documentation说:
不要通过常规JavaScript函数调用Hook。相反,您可以:
✅从React函数组件中调用Hook。
✅从自定义挂钩中呼叫挂钩。
正如@AsafAviv所说,您应该将HOC重构为自定义钩子,以避免违反Rules of Hooks。
React如何将Hook调用与组件相关联?
React跟踪当前渲染的组件。多亏了挂钩规则,我们知道挂钩只能从React组件(或自定义挂钩-也只能从React组件调用)中调用。
每个组件都有一个内部的“内存单元”列表。它们只是JavaScript对象,我们可以在其中放置一些数据。当您调用类似于useState()的Hook时,它将读取当前单元格(或在第一个渲染期间将其初始化),然后将指针移至下一个单元格。这就是多个useState()调用的方式分别获得独立的本地状态的方式。
答案 1 :(得分:2)
转换
props => {
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
};
将您的HOC置于函数内部(当在HOC返回的箭头函数中使用时,反应钩/规则钩将显示您显示的警告)
因此,将其更改为
const Wrapper = Component =>
function Comp(props) {
React.useEffect(() => {
console.log("useEffect");
}, []);
return <Component {...props} />;
};
效果就会被触发。
答案 2 :(得分:0)
您可以在功能组件或自定义挂钩中使用react挂钩。 重写您的HOC:
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)
答案 3 :(得分:0)
Short Answer
:您只需要将回调更改为 PascalCase 函数或 useSomething 函数。这是因为 eslint 规则有一些启发式方法,您需要遵循这些规则才能检测组件。
您需要将代码更改为
const Wrapper = Component => {
return function WithWrapper(props){
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
}
}
答案 4 :(得分:-1)
这是我避免错误的建议
对我有用
`
import * as React from "react";
const Hello = props => <p>Hello {props.name}</p>;
const Wrapper = Component => function WrapperFn(props) {
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
};
export default Wrapper(Hello);
`