Reputation: 543
I'm trying to rewrite a React class component into a functional hooks-based component, but i cannot figure out how to do it. The component logic and JSX looks something like this:
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]}
/>
</>)
Where the function i'm currently rewriting is onClearSearchBox:
private _onClearSearchBox() {
this.setState({ menuItems: { ...this.state.menuItemsFullList } });
}
I tried naively rewriting it using hooks which turned the setState into this:
function onClearSearchBox() {
useEffect(() => setMenuItems(menuItemsFullList));
}
This does not work and i do not know how to restructure the code, as i cannot call hooks inside a non-React component function. Moving it into the React component function as an inner function does not work either.
The error message i'm getting is:
Uncaught Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component...
I believe my mindset is still stuck to the class-based structure, as i cannot figure out how i would go about and refactoring the LeftPanel. How should i go about refactoring _onClearSearchBox to make it work with hooks?
Upvotes: 0
Views: 6266
Reputation: 82096
useEffect is the wrong hook for this, from the docs:
If you’re familiar with React class lifecycle methods, you can think of useEffect Hook as
componentDidMount
,componentDidUpdate
, andcomponentWillUnmount
combined.
In your example, you need control over when to want to call the code e.g. on a button click. I'd say useCallback would be the most appropriate hook here:
const onClearSearchbox = useCallback(() => {
setMenuItemsFullList(props.items);
}, [props.items]);
...
<SearchBox onClear={onClearSearchBox} ... />
Upvotes: 1