在 HoC 中使用 React Hooks 时的警告
Warning when using react hooks in HoC
我创建了一个高阶组件,它应该为我的组件添加一些额外的功能。但是,当我在此组件中使用反应挂钩时,我收到以下 eslint 警告。
React Hook "React.useEffect" cannot be called inside a callback. React
Hooks must be called in a React function component or a custom React
Hook function. (react-hooks/rules-of-hooks)
为什么我会收到此警告?在 HoC 中使用 hook 被认为是不好的做法吗?
最小示例:
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
official React Hooks documentation 说:
Don’t call Hooks from regular JavaScript functions. Instead, you can:
✅ Call Hooks from React function components.
✅ Call Hooks from custom Hooks.
正如@AsafAviv 所说,您应该将 HOC 重构为自定义挂钩以避免违反 Rules of Hooks。
顺便说一下原因是described in the FAQ:
How does React associate Hook calls with components?
React keeps track of the currently rendering component. Thanks to the Rules of Hooks, we know that Hooks are only called from React components (or custom Hooks — which are also only called from React components).
There is an internal list of “memory cells” associated with each component. They’re just JavaScript objects where we can put some data. When you call a Hook like useState(), it reads the current cell (or initializes it during the first render), and then moves the pointer to the next one. This is how multiple useState() calls each get independent local state.
转换
props => {
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
};
在你的 HOC 内部到一个函数(react-hooks/rules-of-hooks 抛出你在 HOC 返回的箭头函数中使用时显示的警告)
所以,将其更改为
const Wrapper = Component =>
function Comp(props) {
React.useEffect(() => {
console.log("useEffect");
}, []);
return <Component {...props} />;
};
效果被触发。
您可以在功能组件或自定义 Hooks 中使用 React Hooks。
重写你的 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)
Short Answer
:您只需将回调更改为 PascalCase 函数或 useSomething 函数即可。这是因为 eslint 规则有一些启发式,您需要遵循这些启发式才能检测组件。
您需要将代码更改为
const Wrapper = Component => {
return function WithWrapper(props){
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
}
}
在定义 HoC 的文件中,只需将以下内容添加到文件顶部:
/* eslint-disable react-hooks/rules-of-hooks */
Hooks and higher-order components是两个完全不同的东西。说 HoC 可以用 hook 代替的人要么从未真正写过 HoC,要么从未玩过语义游戏。
当我编写 HoC 时,我经常不得不禁用 rules-of-hooks
eslint 规则,因为该规则对于它认为是钩子或组件的东西来说太严格了。 HoC 更像是一个组件而不是一个钩子,但规则不承认这一点。
只需将名称更改为小写
喜欢 :
withWrrapperHOC = Comp => props => {
useEffect(()=>{
//...
},[])
return (<Comp {...props}>)
}
我创建了一个高阶组件,它应该为我的组件添加一些额外的功能。但是,当我在此组件中使用反应挂钩时,我收到以下 eslint 警告。
React Hook "React.useEffect" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function. (react-hooks/rules-of-hooks)
为什么我会收到此警告?在 HoC 中使用 hook 被认为是不好的做法吗?
最小示例:
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
official React Hooks documentation 说:
Don’t call Hooks from regular JavaScript functions. Instead, you can:
✅ Call Hooks from React function components.
✅ Call Hooks from custom Hooks.
正如@AsafAviv 所说,您应该将 HOC 重构为自定义挂钩以避免违反 Rules of Hooks。
顺便说一下原因是described in the FAQ:
How does React associate Hook calls with components?
React keeps track of the currently rendering component. Thanks to the Rules of Hooks, we know that Hooks are only called from React components (or custom Hooks — which are also only called from React components).
There is an internal list of “memory cells” associated with each component. They’re just JavaScript objects where we can put some data. When you call a Hook like useState(), it reads the current cell (or initializes it during the first render), and then moves the pointer to the next one. This is how multiple useState() calls each get independent local state.
转换
props => {
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
};
在你的 HOC 内部到一个函数(react-hooks/rules-of-hooks 抛出你在 HOC 返回的箭头函数中使用时显示的警告)
所以,将其更改为
const Wrapper = Component =>
function Comp(props) {
React.useEffect(() => {
console.log("useEffect");
}, []);
return <Component {...props} />;
};
效果被触发。
您可以在功能组件或自定义 Hooks 中使用 React Hooks。 重写你的 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)
Short Answer
:您只需将回调更改为 PascalCase 函数或 useSomething 函数即可。这是因为 eslint 规则有一些启发式,您需要遵循这些启发式才能检测组件。
您需要将代码更改为
const Wrapper = Component => {
return function WithWrapper(props){
React.useEffect(() => {
// Do something here
}, []);
return <Component {...props} />;
}
}
在定义 HoC 的文件中,只需将以下内容添加到文件顶部:
/* eslint-disable react-hooks/rules-of-hooks */
Hooks and higher-order components是两个完全不同的东西。说 HoC 可以用 hook 代替的人要么从未真正写过 HoC,要么从未玩过语义游戏。
当我编写 HoC 时,我经常不得不禁用 rules-of-hooks
eslint 规则,因为该规则对于它认为是钩子或组件的东西来说太严格了。 HoC 更像是一个组件而不是一个钩子,但规则不承认这一点。
只需将名称更改为小写 喜欢 :
withWrrapperHOC = Comp => props => {
useEffect(()=>{
//...
},[])
return (<Comp {...props}>)
}