303

I am getting this warning in react:

index.js:1 Warning: Cannot update a component (`ConnectFunction`) 
while rendering a different component (`Register`). To locate the 
bad setState() call inside `Register` 

I went to the locations indicated in the stack trace and removed all setstates but the warning still persists. Is it possible this could occur from redux dispatch?

my code:

register.js

class Register extends Component {
  render() {
    if( this.props.registerStatus === SUCCESS) { 
      // Reset register status to allow return to register page
      this.props.dispatch( resetRegisterStatus())  # THIS IS THE LINE THAT CAUSES THE ERROR ACCORDING TO THE STACK TRACE
      return <Redirect push to = {HOME}/>
    }
    return (
      <div style = {{paddingTop: "180px", background: 'radial-gradient(circle, rgba(106,103,103,1) 0%, rgba(36,36,36,1) 100%)', height: "100vh"}}>
        <RegistrationForm/>
      </div>
    );
  }
}

function mapStateToProps( state ) {
  return {
    registerStatus: state.userReducer.registerStatus
  }
}

export default connect ( mapStateToProps ) ( Register );

function which triggers the warning in my registerForm component called by register.js

handleSubmit = async () => {
    if( this.isValidForm() ) { 
      const details = {
        "username": this.state.username,
        "password": this.state.password,
        "email": this.state.email,
        "clearance": this.state.clearance
      }
      await this.props.dispatch( register(details) )
      if( this.props.registerStatus !== SUCCESS && this.mounted ) {
        this.setState( {errorMsg: this.props.registerError})
        this.handleShowError()
      }
    }
    else {
      if( this.mounted ) {
        this.setState( {errorMsg: "Error - registration credentials are invalid!"} )
        this.handleShowError()
      }
    }
  }

Stacktrace:

Stacktrace

Tamjid
  • 4,326
  • 4
  • 23
  • 46
  • 1
    there's a big thread on it here: https://github.com/facebook/react/issues/18178. are you able to post the stacktrace (not all of it, just the relevant parts) or tell us exactly the line it's referring to? – Red Baron Jun 12 '20 at 06:56
  • @RedBaron added the stacktrace – Tamjid Jun 14 '20 at 23:34

19 Answers19

277

This warning was introduced since React V16.3.0.

If you are using functional components you could wrap the setState call into useEffect.

Code that does not work:

const HomePage = (props) => {
    
  props.setAuthenticated(true);

  const handleChange = (e) => {
    props.setSearchTerm(e.target.value.toLowerCase());
  };

  return (
    <div key={props.restInfo.storeId} className="container-fluid">
      <ProductList searchResults={props.searchResults} />
    </div>
  );
};

Now you can change it to:

const HomePage = (props) => {
  // trigger on component mount
  useEffect(() => {
    props.setAuthenticated(true);
  }, []);

  const handleChange = (e) => {
    props.setSearchTerm(e.target.value.toLowerCase());
  };

  return (
    <div key={props.restInfo.storeId} className="container-fluid">
      <ProductList searchResults={props.searchResults} />
    </div>
  );
};
Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
Emile ASTIH
  • 2,894
  • 2
  • 9
  • 8
  • 40
    And you should add second parameter ```[]``` to ```useEffect``` if you want this to run just once (not everytime state gets updated). – Grengas Sep 29 '20 at 14:32
  • 6
    This fixed it for me. Now I'm trying to figure out why. Any help? – Ken Sawyerr Oct 14 '20 at 23:42
  • 3
    @sawyerrken [This link](https://reactjs.org/blog/2020/02/26/react-v16.13.0.html#new-warnings) may answer part of the why, but overall, the issue continues to confuse me as I try to resolve the error. – tim.rohrer Nov 19 '20 at 01:38
  • 7
    In my case, I fixed by moving `dispatch` in the `useEffect` – Hamid Shoja Jun 10 '21 at 11:06
  • 1
    It's sometimes not possible to stick everything inside of a useEffect, i.e., when the state to set is the return of another hook (since you cant put hooks in useEffect). – John Miller Aug 25 '21 at 18:05
  • 7
    can you elaborate on **why this works**? – Normal May 13 '22 at 15:48
  • this solution is great, but what if the parent state update method was used by multiple child components? in this case I will have to write useEffect in all of those child components. Is there a way to useEffect once among all those children? maybe inside the parent itself without having the child component worry about the "must-be-abstracted" inner details of the parent component? – Normal May 15 '22 at 08:39
  • @Normal & KenSawyerr -- does [Brett's answer help](https://stackoverflow.com/questions/62336340/cannot-update-a-component-while-rendering-a-different-component-warning#comment124536912_65911215)? – ruffin Feb 06 '23 at 20:40
  • Wrapping in `useEffect` did it for me. Apparently the function (which included a `setState` in a superior component) was called more than once. Curiously, in my console there were two stack traces: one for this error, and immediately after it, a stack trace for the following error `Uncaught TypeError: Do not know how to serialize a BigInt` which was thrown out of the guts of `redux.js`. I've no idea why but the fix removed both errors. – Marcus Junius Brutus May 08 '23 at 18:27
  • 1
    @HamidShoja , your solution **worked for me**, I was using `dispatch` outside `useEffect` and it causing problem. – Cypher or KJ Jul 21 '23 at 05:52
71

I just had this issue and it took me a bit of digging around before I realised what I'd done wrong – I just wasn't paying attention to how I was writing my functional component.

I was doing this:

const LiveMatches = (props: LiveMatchesProps) => {
  const {
    dateMatches,
    draftingConfig,
    sportId,
    getDateMatches,
  } = props;

  if (!dateMatches) {
    const date = new Date();
    getDateMatches({ sportId, date });
  };

  return (<div>{component stuff here..}</div>);
};

I had just forgotten to use useEffect before dispatching my redux call of getDateMatches()

So it should have been:

const LiveMatches = (props: LiveMatchesProps) => {
  const {
    dateMatches,
    draftingConfig,
    sportId,
    getDateMatches,
  } = props;

  useEffect(() => {
    if (!dateMatches) {
      const date = new Date();
      getDateMatches({ sportId, date });
    }
  }, [dateMatches, getDateMatches, sportId]);

  return (<div>{component stuff here..}</div>);
};
Michael Mior
  • 28,107
  • 9
  • 89
  • 113
Brett East
  • 4,022
  • 2
  • 20
  • 31
  • 3
    How come putting your code into useEffect removes this warning? – Plumpie Dec 21 '21 at 12:23
  • 4
    @Plumpie because react works in 'cycles' it keeps track of what is rendered and when to update and render new components. It does this through the use of hooks or lifecycle methods. If this function is not inside the useEffect hook, then the component will attempt to call it on every rerender, and that also updates the component - out of order with what react would like. Moving the code into a hook, allows react to update components in the correct order so that it can keep track as things change. – Brett East Dec 22 '21 at 15:27
62

Please read the error message thoroughly. Mine was pointing to SignIn Component that had a bad setState. I had an onPress that was not an Arrow function.

It was like this:

onPress={navigation.navigate("Home", { screen: "HomeScreen" })}

I changed it to this:

onPress={() => navigation.navigate("Home", { screen: "HomeScreen" }) }

My error message was:

Warning: Cannot update a component (ForwardRef(BaseNavigationContainer)) while rendering a different component (SignIn). To locate the bad setState() call inside SignIn, follow the stack trace as described in https://reactjs.org/link/setstate-in-render in SignIn (at SignInScreen.tsx:20)

Jasperan
  • 2,154
  • 1
  • 16
  • 40
shiraz27
  • 1,898
  • 18
  • 14
  • 7
    This is what happened to me when I was coding feeling half sleepy. Thank you for saving me! – hd3adcode Jul 26 '22 at 05:59
  • onPress={() => navigation. Navigate("HomeScreen") } – ilidiocn Mar 04 '23 at 06:52
  • Why is the arrow function wrapper necessary? – CamHart Jul 11 '23 at 01:22
  • @CamHart In simple terms, as mentioned in the error message, the cause is : updating the state of different components simultaneously. the arrow function wrapper allows you to defer the execution of the navigation function until the button is pressed, avoiding conflicts and errors related to updating state during the rendering process. – shiraz27 Jul 11 '23 at 08:11
22

I fixed this issue by removing the dispatch from the register components render method to the componentwillunmount method. This is because I wanted this logic to occur right before redirecting to the login page. In general it's best practice to put all your logic outside the render method so my code was just poorly written before. Hope this helps anyone else in future :)

My refactored register component:

class Register extends Component {

  componentWillUnmount() {
    // Reset register status to allow return to register page
    if ( this.props.registerStatus !== "" ) this.props.dispatch( resetRegisterStatus() )
  }

  render() {
    if( this.props.registerStatus === SUCCESS ) { 
      return <Redirect push to = {LOGIN}/>
    }
    return (
      <div style = {{paddingTop: "180px", background: 'radial-gradient(circle, rgba(106,103,103,1) 0%, rgba(36,36,36,1) 100%)', height: "100vh"}}>
        <RegistrationForm/>
      </div>
    );
  }
}

Tamjid
  • 4,326
  • 4
  • 23
  • 46
  • 1
    you could also make some detructuring, e.g: ```const {someDispatch} = props;```, then use your dispatch wherever you want. – Arp Aug 09 '20 at 01:21
19

I think that this is important. It's from this post that @Red-Baron pointed out:

@machineghost : I think you're misunderstanding what the message is warning about.

There's nothing wrong with passing callbacks to children that update state in parents. That's always been fine.

The problem is when one component queues an update in another component, while the first component is rendering.

In other words, don't do this:

function SomeChildComponent(props) {
    props.updateSomething();
    return <div />
}

But this is fine:

function SomeChildComponent(props) {
    // or make a callback click handler and call it in there
    return <button onClick={props.updateSomething}>Click Me</button>
}

And, as Dan has pointed out various times, queuing an update in the same component while rendering is fine too:

function SomeChildComponent(props) {
  const [number, setNumber] = useState(0);

  if(props.someValue > 10 && number < 5) {
    // queue an update while rendering, equivalent to getDerivedStateFromProps
    setNumber(42);
  }

  return <div>{number}</div>
}
Spiff
  • 3,873
  • 4
  • 25
  • 50
  • In my case, I was using `useState` to store the callback, because the callback could change. Moving to `useCallback` instead fixed the problem – Francisco Gomes Feb 01 '23 at 23:42
15

If useEffect cannot be used in your case or if the error is NOT because of Redux

I used setTimeout to redirect one of the two useState variables to the callback queue.

I have one parent and one child component with useState variable in each of them. The solution is to wrap useState variable using setTimeout:

setTimeout(() => SetFilterData(data), 0);

Example below

Parent Component

import ExpenseFilter from '../ExpensesFilter'
    
function ExpensesView(props) {
    
    const [filterData, SetFilterData] = useState('')
    
    const GetFilterData = (data) => {
       // SetFilterData(data);

       //*****WRAP useState VARIABLE INSIDE setTimeout WITH 0 TIME AS BELOW.*****
       setTimeout(() => SetFilterData(data), 0);
    
    }
    
    const filteredArray = props.expense.filter(expenseFiltered => 
      expenseFiltered.dateSpent.getFullYear().toString() === filterData);
    
    
    return (
    <Window>
      <div>
        <ExpenseFilter FilterYear = {GetFilterData}></ExpenseFilter>

Child Component

const ExpensesFilter = (props) => {
    
    const [filterYear, SetFilterYear] = useState('2022')
    
    const FilterYearListener = (event) => {
        event.preventDefault()
        SetFilterYear(event.target.value)
    }
    
    props.FilterYear(filterYear)
    
    return (
double-beep
  • 5,031
  • 17
  • 33
  • 41
MIDHUN V
  • 165
  • 1
  • 6
  • 3
    This works because `setTimeout()` is a blocking function forcing the `setFilterData` function to no longer be asynchronous. This is not how state hooks are meant to work and is basically a kluge that may result in unexpected behavior. – RyanNerd Oct 24 '21 at 20:11
  • 2
    `setImmediate` would be a good alternative. – Danny Apostolov Dec 22 '21 at 18:51
  • 2
    @DannyApostolov according to MDN setImmediate is non-standard and should not be used on production sites facing the web. – hkiame Feb 14 '22 at 14:05
  • 1
    @hkiame sorry, I was thinking "react native" all the time... you're totally right! – Danny Apostolov Feb 14 '22 at 15:29
  • @RyanNerd you made me suspect that this method is not the best, can you elaborate more on that? – Normal May 15 '22 at 08:42
  • UPDATE: WARNING!! this approach keeps calling the state forever, try to `console.log("called the state")` inside the `setTimeout` to see: ex: `setTimeout(() => {SetFilterData(data); console.log("called")}, 0);` // prints called 999.x times – Normal May 15 '22 at 08:59
  • @Normal A better approach is to have a `useEffect()` to capture changes to state and do the fetch and update inside: `useEffect(()=>{setFilterData(dataFromFetch)}, [props.expense.filter])` Assuming that `props.expense.filter` is the state change variable you want to monitor for changes. – RyanNerd May 18 '22 at 11:10
6

Using React and Material UI (MUI) I changed my code from:

<IconButton onClick={setOpenDeleteDialog(false)}>
        <Close />
      </IconButton>

To:

<IconButton onClick={() => setOpenDeleteDialog(false)}>
        <Close />
      </IconButton>

Simple fix

EspenHW
  • 61
  • 1
  • 2
  • 1
    I had a similar, I had an event that I was wrongly attaching a function. – Ivan Jul 07 '22 at 13:25
  • 2
    Just a "me too" here, I was executing the handler during the render instead of assigning it. In my case I was doing something like this: instead of . – BitsAndBytes Jul 10 '22 at 16:05
5

If you use React Navigation and you are using the setParams or setOptions you must put these inside method componentDidMount() of class components or in useEffects() hook of functional components.

3

Minimal reproducing example

I was a bit confused as to what exactly triggers the problem, having a minimal immediately runnable example helped me grasp it a little better:

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone@7.14.7/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function NotMain(props) {
  props.setN(1)
  return <div>NotMain</div>
}

function Main(props) {
  const [n, setN] = React.useState(0)
  return <>
    <NotMain setN={setN} />
    <div>Main {n}</div>
  </>
}

ReactDOM.render(
  <Main/>,
  document.getElementById('root')
);
</script>
</body>
</html>

fails with error:

react-dom.development.js:61 Warning: Cannot update a component (`Main`) while rendering a different component (`NotMain`). To locate the bad setState() call inside `NotMain`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render

followed by a stack trace:

    at NotMain (<anonymous>:16:9)
    at Main (<anonymous>:21:31)

Presumably 16:9 would be the exact line where props.setN(1) is being called from, but the line numbers are a bit messed up because of the Babel JSX translation.

The solution like many other answers said is to do instead:

function NotMain(props) {
  React.useEffect(() => { props.setN(1) }, [])
  return <div>NotMain</div>
}

Intuitively, I think that the general idea of why this error happens is that:

You are not supposed to updat state from render methods, otherwise it could lead to different results depending on internal the ordering of how React renders things.

and when using functional components, the way to do that is to use hooks. In our case, useEffect will run after rendering is done, so we are fine doing that from there.

When using classes this becomes slightly more clear and had been asked for example at:

When using functional components however, things are conceptually a bit more mixed, as the component function is both the render, and the code that sets up the callbacks.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
2

My case was using setState callback, instead of setState + useEffect

BAD ❌

  const closePopover = useCallback(
    () =>
      setOpen((prevOpen) => {
        prevOpen && onOpenChange(false);
        return false;
      }),
    [onOpenChange]
  );

GOOD ✅

  const closePopover = useCallback(() => setOpen(false), []);

  useEffect(() => onOpenChange(isOpen), [isOpen, onOpenChange]);
DamianoPantani
  • 1,168
  • 2
  • 13
  • 23
2

Cannot update a component while rendering a different component warning

I have the same problem but when I dispatch an action inside a component rendered. You should dispatch the action inside useEffect hook to fix that problem


//dispatch action to inform user that 'Marked days already have hours!'
  React.useEffect(() => {
    if (btn_class == 'redButton') {
      dispatch({ type: ActionType.ADD_NOTIFICATION, payload: 'Marked days already have hours!' });
    } else {
      dispatch({ type: ActionType.ADD_NOTIFICATION, payload: '' });
    }
  }, [btn_class, dispatch]);

also use union type for btn-class variable *`

type ButtonState = 'btnAddDay' | 'redButton' | 'btnAddDayBlue' | 'btnAddDayGreen';

`*

1

I was facing same issue, The fix worked for me was if u are doing

setParams/setOptions

outside of useEffect then this issue is occurring. So try to do such things inside useEffect. It'll work like charm

1

TL;DR; For my case, what I did to fix the warning was to change from useState to useRef

react_devtools_backend.js:2574 Warning: Cannot update a component (`Index`) while rendering a different component (`Router.Consumer`). To locate the bad setState() call inside `Router.Consumer`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
    at Route (http://localhost:3000/main.bundle.js:126692:29)
    at Index (http://localhost:3000/main.bundle.js:144246:25)
    at Switch (http://localhost:3000/main.bundle.js:126894:29)
    at Suspense
    at App
    at AuthProvider (http://localhost:3000/main.bundle.js:144525:23)
    at ErrorBoundary (http://localhost:3000/main.bundle.js:21030:87)
    at Router (http://localhost:3000/main.bundle.js:126327:30)
    at BrowserRouter (http://localhost:3000/main.bundle.js:125948:35)
    at QueryClientProvider (http://localhost:3000/main.bundle.js:124450:21)

The full code for the context of what I did (changed from the lines with // OLD: to the line above them). However this doesn't matter, just try changing from useState to useRef!!

import { HOME_PATH, LOGIN_PATH } from '@/constants';
import { NotFoundComponent } from '@/routes';
import React from 'react';
import { Redirect, Route, RouteProps } from 'react-router-dom';
import { useAccess } from '@/access';
import { useAuthContext } from '@/contexts/AuthContext';
import { AccessLevel } from '@/models';

type Props = RouteProps & {
  component: Exclude<RouteProps['component'], undefined>;
  requireAccess: AccessLevel | undefined;
};

export const Index: React.FC<Props> = (props) => {
  const { component: Component, requireAccess, ...rest } = props;

  const { isLoading, isAuth } = useAuthContext();
  const access = useAccess();
  const mounted = React.useRef(false);
  // OLD: const [mounted, setMounted] = React.useState(false);

  return (
    <Route
      {...rest}
      render={(props) => {
        // If in indentifying authentication state as the page initially loads, render a blank page
        if (!mounted.current && isLoading) return null;
        // OLD: if (!mounted && isLoading) return null;

        // 1. Check Authentication is one step
        if (!isAuth && window.location.pathname !== LOGIN_PATH)
          return <Redirect to={LOGIN_PATH} />;
        if (isAuth && window.location.pathname === LOGIN_PATH)
          return <Redirect to={HOME_PATH} />;

        // 2. Authorization is another
        if (requireAccess && !access[requireAccess])
          return <NotFoundComponent />;

        mounted.current = true;
        // OLD: setMounted(true);
        return <Component {...props} />;
      }}
    />
  );
};

export default Index;
Loi Nguyen Huynh
  • 8,492
  • 2
  • 29
  • 52
  • I believe setting `ref.current=` will not cause a rerender. Could be an issue because `setState` is primarly used for rerendering with new state. – 700 Software Jan 24 '22 at 20:06
1

My example.

Code with that error:

<Form
    initialValues={{ ...kgFormValues, dataflow: dataflows.length > 0 ? dataflows[0].df_tpl_key : "" }}
    onSubmit={() => {}}
    render={({values, dirtyFields }: any) => {
      
      const kgFormValuesUpdated = {
        proj_key: projectKey,
        name: values.name,
        description: values.description,
        public: values.public,
        dataflow: values.dataflow,
        flavours: flavoursSelected,
        skipOCR: values.skipOCR
      };

      if (!_.isEqual(kgFormValues, kgFormValuesUpdated)) {
        setNewKgFormValues(kgFormValuesUpdated);
      }

Working Code:

 <Form
    initialValues={{ ...kgFormValues, dataflow: dataflows.length > 0 ? dataflows[0].df_tpl_key : "" }}
    onSubmit={() => {}}
    render={({ values, dirtyFields }: any) => {
      useEffect(() => {
        const kgFormValuesUpdated = {
          proj_key: projectKey,
          name: values.name,
          description: values.description,
          public: values.public,
          dataflow: values.dataflow,
          flavours: flavoursSelected,
          skipOCR: values.skipOCR
        };

        if (!_.isEqual(kgFormValues, kgFormValuesUpdated)) {
          setNewKgFormValues(kgFormValuesUpdated);
        }
      }, [values]);

      return (
Rafa
  • 31
  • 3
1

I had the same problem. I was setting some state that was storing a function like so:

// my state definition
const [onConfirm, setOnConfirm] = useState<() => void>();

// then I used this piece of code to update the state
function show(onConfirm: () => void) {
    setOnConfirm(onConfirm);
}

The problem was from setOnConfirm. In React, setState can take the new value OR a function that returns the new value. In this case React wanted to get the new state from calling onConfirm which is not correct.

changing to this resolved my issue:

setOnConfirm(() => onConfirm);
SMhd Asadi
  • 161
  • 12
1

I was able to solve this after coming across a similar question in GitHub which led me to this comment showing how to pinpoint the exact line within your file causing the error. I wasn't aware that the stack trace was there. Hopefully this helps someone!

See below for my fix. I simply converted the function to use callback.

Old code

function TopMenuItems() {
  const dispatch = useDispatch();

  function mountProjectListToReduxStore(projects) {
    const projectDropdown = projects.map((project) => ({
      id: project.id,
      name: project.name,
      organizationId: project.organizationId,
      createdOn: project.createdOn,
      lastModifiedOn: project.lastModifiedOn,
      isComplete: project.isComplete,
    }));
    projectDropdown.sort((a, b) => a.name.localeCompare(b.name));
    dispatch(loadProjectsList(projectDropdown));
    dispatch(setCurrentOrganizationId(projectDropdown[0].organizationId));
  }
};

New code

function TopMenuItems() {
  const dispatch = useDispatch();

  const mountProjectListToReduxStore = useCallback((projects) => {
    const projectDropdown = projects.map((project) => ({
      id: project.id,
      name: project.name,
      organizationId: project.organizationId,
      createdOn: project.createdOn,
      lastModifiedOn: project.lastModifiedOn,
      isComplete: project.isComplete,
    }));
    projectDropdown.sort((a, b) => a.name.localeCompare(b.name));
    dispatch(loadProjectsList(projectDropdown));
    dispatch(setCurrentOrganizationId(projectDropdown[0].organizationId));
  }, [dispatch]);
};
Meredith Murfin
  • 841
  • 4
  • 4
1

I faced a similar issue. The cause of the error was the "useLocation()" hook of react-router-dom. I have moved it to before of the "return <Navigate to ..." then it was fixed.

I don't know what was changed but it worked. If anybody could explain this, I will be glad...

My old code is:


import { Navigate, useLocation } from 'react-router-dom';


export const Navigation = ({ children }: React.PropsWithChildren): JSX.Element => {

    const location = useLocation(); //  ---> Cause of the error

    if (Authenticator.isAuthenticated() && window.sessionStorage.getItem('isAuthenticated') === 'true') {
      return <>{children}</>;
    }


    return <Navigate to="/login" state={{ from: location }} replace />;
  };

Correct version is:


export const Navigation = ({ children }: React.PropsWithChildren): JSX.Element => {
    if (Authenticator.isAuthenticated() && window.sessionStorage.getItem('isAuthenticated') === 'true') {
      return <>{children}</>;
    }

    const location = useLocation(); // moved here and fixed

    return <Navigate to="/login" state={{ from: location }} replace />;
  };

My given error was:

Warning: Cannot update a component (`Header`) while rendering a different 
component (`Unknown`). To locate the bad setState() call inside `Unknown`, 
follow the stack trace as described in 
https://reactjs.org/link/setstate-in-render
    at http://localhost:3001/static/js/bundle.js:251:5
    at RenderedRoute (http://localhost:3001/static/js/bundle.js:60935:5)
    at Outlet (http://localhost:3001/static/js/bundle.js:61419:26)
    at aside
    at section
    at Drawer
Serkan KONAKCI
  • 1,100
  • 11
  • 16
0

I got this when I was foolishly invoking a function that called dispatch instead of passing a reference to it for onClick on a button.

  const quantityChangeHandler = (direction) => {
    dispatch(cartActions.changeItemQuantity({title, quantityChange: direction}));
  }
...
          <button onClick={() => quantityChangeHandler(-1)}>-</button>
          <button onClick={() => quantityChangeHandler(1)}>+</button>

Initially, I was directly calling without the fat arrow wrapper.

JohnOpincar
  • 5,620
  • 3
  • 35
  • 38
-1

Using some of the answers above, i got rid of the error with the following:

from

if (value === "newest") {
  dispatch(sortArticlesNewest());
} else {
  dispatch(sortArticlesOldest());
}

this code was on my component top-level

to

    const SelectSorting = () => {
  const dispatch = useAppDispatch();

  const {value, onChange} = useSelect();

  useEffect(() => {
    if (value === "newest") {
      dispatch(sortArticlesNewest());
    } else {
      dispatch(sortArticlesOldest());
    }
  }, [dispatch, value]);