首页 > 解决方案 > 在嵌套函数中使用钩子

问题描述

我正在尝试将 React 类组件重写为基于功能挂钩的组件,但我不知道该怎么做。组件逻辑和 JSX 看起来像这样:

export class LeftPanel extends React.Component<ILeftPanelProps, ILeftPanelState> {

const [menuItemsFullList, setMenuItemsFullList] = useState([{links: []}] as any[]);

useEffect(() => {
    const { links } = props;

    setMenuItemsFullList(links);
}, props.links);
....

return (<>
        <SearchBox
            onChange={_onSearch}
            onClear={_onClearSearchBox}
        />
            <NavList
                listEntries={[menuItems]}
            />
</>)

我目前正在重写的功能是 onClearSearchBox:

private _onClearSearchBox() {
    this.setState({ menuItems: { ...this.state.menuItemsFullList } });
}

我尝试使用将 setState 变成这样的钩子天真地重写它:

function onClearSearchBox() {
     useEffect(() => setMenuItems(menuItemsFullList));
}

这不起作用,我不知道如何重构代码,因为我无法在非 React 组件函数中调用钩子。将其作为内部函数移动到 React 组件函数中也不起作用。

我收到的错误消息是:

未捕获的不变违规:无效的挂钩调用。钩子只能在函数组件的主体内部调用...

我相信我的思维方式仍然停留在基于类的结构上,因为我无法弄清楚我将如何进行并重构 LeftPanel。我应该如何重构 _onClearSearchBox 以使其与钩子一起使用?

标签: reactjsreact-hooks

解决方案


useEffect是错误的钩子,来自文档:

如果您熟悉 React 类生命周期方法,您可以将 useEffect Hook 视为componentDidMount, componentDidUpdate, 和componentWillUnmount组合。

在您的示例中,您需要控制何时要调用代码,例如单击按钮。我想说useCallback将是这里最合适的钩子:

const onClearSearchbox = useCallback(() => {
  setMenuItemsFullList(props.items);
}, [props.items]);
...
<SearchBox onClear={onClearSearchBox} ... />

推荐阅读