DEV Community

Sai Avinash Duddupudi
Sai Avinash Duddupudi

Posted on

setState in Reactjs is not a function

I'm new to react and I am trying to hit an API using fetch and then setState to a state variable but it is throwing the error as

Unhandled Rejection (TypeError): Object(...) is not a function
Enter fullscreen mode Exit fullscreen mode

CodeSandboxLink
Below is the code

import React from "react";
import { useState, useEffect, setState } from "react";
import "./styles.css";

export default function App() {
  const [person, setPerson] = useState([]);
  fetch("https://jsonplaceholder.typicode.com/users")
    .then((response) => {
      return response.json();
    })
    .then((data) => {
      setState(data);
    });
  console.log("dasdasd", person);
  return <div className="App">{JSON.stringify(person)}</div>;
}
Enter fullscreen mode Exit fullscreen mode

Please suggest where I am doing wrong.

Discussion (15)

Collapse
syntaxhacker profile image
syntaxhacker

if you are new to react dont bump into react hooks at first . read and follow some react introduction posts on this platform and by the way setState is not a react function .

working code

import React from "react";
import { useState } from "react";
import "./styles.css";

export default function App() {
  const [person, setPerson] = useState([]);
  fetch("https://jsonplaceholder.typicode.com/users")
    .then((response) => {
      return response.json();
    })
    .then((data) => {
      setPerson(data);
    });
  console.log("dasdasd", person);
  return <div className="App">{JSON.stringify(person)}</div>;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
saiavinashiitr profile image
Sai Avinash Duddupudi Author • Edited on

hey, when I ran this code, it is repeatedly hitting the API and never stopping. I want it to run only once

Collapse
syntaxhacker profile image
syntaxhacker • Edited on

If you only want to run useEffect once , you can give it an empty array as second argument.

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => {
        return response.json();
      })
      .then((data) => {
        setPerson(data);
      });
  }, []); 
Enter fullscreen mode Exit fullscreen mode
Thread Thread
saiavinashiitr profile image
Sai Avinash Duddupudi Author • Edited on

yes thanks for useeffect, Now I wanted to pass this person to customers state variable but it is rendering as empty which is exactly why I have not used useEffect in the first place {"data":[]}

import React from "react";
import { useState, useEffect } from "react";
// import "./styles.css";

export default function App() {
  const [person, setPerson] = useState([]);
  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => {
        return response.json();
      })
      .then((data) => {
        setPerson(data); // You Need this For set Person to `state person`
      });
  }, []);
  console.log("dasdasd", person);
  const [customers, setCustomers] = useState({ data: person });
  return <div className="App">{JSON.stringify(customers)}</div>;
}
Enter fullscreen mode Exit fullscreen mode
Thread Thread
buraksaraloglu profile image
Burak Saraloglu

You can check for data !== null && return (...) for conditional rendering. Since it will rerender after data loaded, it would also prevent from empty rendering.

Thread Thread
saiavinashiitr profile image
Sai Avinash Duddupudi Author • Edited on

It is being empty forever, not re-rendering at all.

Thread Thread
buraksaraloglu profile image
Burak Saraloglu

I just saw what you did in your customer state. You shouldn't initialize customer state with promise state. What I mean by that is:

export default function App() {
const [person, setPerson] = useState([]);
useEffect(() => {
fetch("jsonplaceholder.typicode.com/users")
.then((response) => {
return response.json();
})
.then((data) => {
setPerson(data); // You Need this For set Person to state person
});
}, []);
console.log("dasdasd", person);

// This is the part which is updated:

const [customers, setCustomers] = useState({});

// Passing person as a dependency will allow customers to update automatically
useEffect(() => {
person !== null && setCustomers({data: person});
}, [person])

return

{JSON.stringify(customers)};

}
Thread Thread
saiavinashiitr profile image
Sai Avinash Duddupudi Author • Edited on
useEffect(() => {
    person !== null && setCustomers({data: person, isLoading: true, filteredData: person});
    }, [person])
Enter fullscreen mode Exit fullscreen mode

By dependency, you mean the above block of code gets called every time until person state is changed?

Thread Thread
buraksaraloglu profile image
Burak Saraloglu

It works like this:
1-) Initial page rendering with empty person state, then renders your fetch effect (the second effect did not process because person === null)
2) After the first effect process is done, it will change the person and we put the person state as a dependency for the second effect, it will re-render. Then obviously it will re-render the part of the document.

So, it will not get called until the person state is changed. It will get called if the person state changes.

Thread Thread
saiavinashiitr profile image
Sai Avinash Duddupudi Author • Edited on

Since we added person as dependency , you said it will re-render when person state is updated. so there might be chances of hitting the API twice right? depending upon the person state?

Please correct me If I am wrong

Thread Thread
buraksaraloglu profile image
Burak Saraloglu

As far as I remember, we should've written API connection in separate effect. So, It shouldn't hit for API twice. It will only recall for customers effect.

PS: There's a solution below: after you call for API, setPerson and setCustomers.

.then((data) => {
setPerson(data);
setCustomers(data) // You Need this For set Person to state person
});

Maybe this can work aswell.

Collapse
syntaxhacker profile image
syntaxhacker

you can just add this right?


.then((data) => {
        setPerson(data); 
        setCustomers(data) // You Need this For set Person to `state person`
      });
Enter fullscreen mode Exit fullscreen mode
Collapse
emmanuelthecoder profile image
Emmanuel Aiyenigba

No. It won't work that way. setState() cannot be called with React hooks.
const [person, setPerson] = useState([])
In the state hook method, the second parameter (in this case setPerson) is what is used to change/update the state.
Now instead of setState(data), do setPerson(data) and it should work just fine.

Collapse
saiavinashiitr profile image
Sai Avinash Duddupudi Author

The reason I am not using setPerson is because it has be wrapped under useEffect hook but I want to pass this person data to another useState Variables.

Since useState happens in initial load, if we use useEffect I wont be able to pass data to useState variables

Collapse
sirseanofloxley profile image
Sean Allin Newell

You still need setPerson. Basically with a functional component using hooks, setState is not defined. Hence your type error.