Hobey823
Hobey823

Reputation: 272

React.js - Redux Hooks Invalid Hook Call

I'm trying to use useDispatch inside my component's render function.

import { useDispatch } from 'react-redux';

I have a input that tries to useDispatch on onChange

onChange={() => useDispatch()(update("test"))}

When onChange is fired, I get this error:

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app
import React, {
    Component
} from 'react';
import {
    useDispatch
} from 'react-redux';
import {
    update
} from '../store/actions';
class Something extends Component {
    render() {
        return (<input onChange={() => useDispatch()(update("test"))}/>)
    }
}

export default Something;

Upvotes: 4

Views: 10374

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1075925

The problem is that you're using it in render in a class component. You can't use hooks in class components. That's why the error message says

Invalid hook call. Hooks can only be called inside of the body of a function component.

(my emphasis). Class components aren't function components. (That's a bit easy to miss, would be good if the list of possible causes mentioned class components specifically.)

So you'd want to make it a function component:

import React, {
    Component
} from 'react';
import {
    useDispatch
} from 'react-redux';
import {
    update
} from '../store/actions';
function Something() {                                              // ***
    return <input onChange={() => useDispatch()(update("test"))}/>; // ***
}                                                                   // ***

export default Something;

Also note the warning in the documentation that the above will cause unnecessary rendering and that you should use useCallback:

import React, {
    Component,
    useCallback
} from 'react';
import {
    useDispatch
} from 'react-redux';
import {
    update
} from '../store/actions';
function Something() {
    const dispatch = useDispatch();            // ***
    const handleChange = useCallback(          // ***
        () => dispatch(update("test")),        // ***
        [dispatch]                             // ***
    );                                         // ***
    return <input onChange={handleChange}/>;   // ***
}

export default Something;

Upvotes: 5

lavor
lavor

Reputation: 1877

Yes you are not using it correctly, try this:

const dispatch = useDispatch()

...
onChange={() => dispatch(update("test"))}

See documentation of useDispatch, there is example of its usage.

Upvotes: 0

Related Questions