0
votes

I am unable to use useContext hook for some reason.

Repo Link for directory structure: REPO URL

Error:

Unhandled Runtime Error

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

My code:

context :

import { createContext, useReducer } from 'react'
export const DataContext = createContext();

const DataProvider = ({ intialState, reducer, children }) => {
    <DataContext.Provider value={useReducer(reducer, intialState)}>
        {children}
    </DataContext.Provider >
}

export default DataProvider;

reducer:

import { types } from './types';

export const initialState = {
    name: '',
    room: ''
}

const reducer = (state, action) => {
    console.log("Calling action", action);
    switch (action.type) {
        case types.SET_NAME:
            return { ...state, name: action.name }
        case types.SET_ROOM:
            return { ...state, name: action.room }
        default:
            return state;
    }
}

Main component that is causing issue :

import { useContext } from 'react';
import { input } from '../hooks/input';
import Link from 'next/link';
import { DataContext } from '../context/DataProvider';
import { types } from '../reducers/types';

const Join = () => {
    const [name, setName] = input('');
    const [room, setRoom] = input('');

    const submit = () => {
        console.log('FORM');
        const [state, dispatch] = useContext(DataContext);
        dispatch({
            type: types.SET_NAME,
            name
        });
        dispatch({
            type: types.SET_ROOM,
            room
        })
    }
    return (
        <div>
            <h1>Join</h1>

            <input onChange={(e) => setName(e)} placeholder="name" />
            <input onChange={(e) => setRoom(e)} placeholder="room" />
            <Link href="/chat">
                <button type="submit" onClick={() => submit()}>Submit</button>
            </Link>

        </div>
    )
}

export default Join;
1
const [state, dispatch] = useContext(DataContext); this is your problem line. As the error says: you can only use hooks in the body of a function component. This is used within a normal function, not the functional component body, so it is not allowed (see rule 2). - Brian Thompson

1 Answers

1
votes

You can only use hooks in the body of a function component. You can't use them in a callback function. So move the use of useContext outside of submit:

const [state, dispatch] = useContext(DataContext);
const submit = () => {
  console.log("FORM");
  dispatch({
    type: types.SET_NAME,
    name,
  });
  dispatch({
    type: types.SET_ROOM,
    room,
  });
};