Jim
Jim

Reputation: 669

problem with fetch in componentDidMount()

my list of users is undefined when i try to console.log it. Maybe i didn't get something ?

I'd like to get my list of users from my api who works (tested with postman) and put it into the console next i'd like to map my users to show it on the app

class Test extends Component {
  constructor(props) {
    super(props);
    this.state = {
      users: [],
    }
  }

  componentDidMount() {
    console.log("component did mount");
    fetch("/user/list")
    .then(res => {
      return res.json();
    })
    .then(users => 
      this.setState({users}, () => 
      console.log("list of users => " + users)));
  }

  render() {
    return (
    <div className="form">
      <ul>
        {this.state.users.map((user) =>
          <li key="user._id">{ user.name }</li>
        )}
      </ul>
    </div>
    );
  }
} export default Test;

Thanks for help !

Upvotes: 0

Views: 1864

Answers (4)

Alexander Jaramillo
Alexander Jaramillo

Reputation: 1

Michael Jasper response help me so much!

I found that fetch with GET method does not work if we pass any request body.

the full example is here https://github.com/alexunjm/todo-list-react

const buildRequestOptions = ({
  method = "GET",
  raw = null, // I had my error here!, with GET raw need to be null
  customHeaders = {name: 'value'},
}) => {
  var myHeaders = buildHeaders(customHeaders);

  var requestOptions = {
    method,
    headers: myHeaders,
    body: raw,
    redirect: "follow",
  };

  return requestOptions;
};

const listTasks = () => {
  const url = `${uriBase}/task/sample`;
  const requestOptions = buildRequestOptions({
    customHeaders: { "Content-Type": "application/json" },
  });
  return fetch(url, requestOptions);
}

const asyncFn = ({
  promiseToWait,
  pendingFn,
  successFn,
  errorFn,
}) => {
  return (dispatch) => {
    dispatch(pendingFn());
    promiseToWait
      .then((res) => {
        if (res.ok) {
          return res.json();
        }
        // handled from server status 422 and 401
        if (res.status === 422) {
          // error message on body from server
          return res.json();
        }
        if (res.status === 401) {
          // custom error message hardcoded
          return {errors: {action: 'no authorized'}}
        }
        console.log("http response no controlled", res);
        return Promise.reject();
      })
      .then((body) => {
        if (body.errors) {
          const errors = Object.keys(body.errors).map(
            (key) => key + " " + body.errors[key]
          );
          dispatch(errorFn(errors.join("; ")));
        } else {
          dispatch(successFn(body));
        }
        return body;
      })
      .catch((error) => {
        console.log("error", error);
        dispatch(errorFn("Unavailable server connection"));
      });
  };
};

const queryTasks = () => {
  return asyncFn({
    promiseToWait: listTasks(),
    pendingFn: apiPending,
    successFn: apiSuccessList,
    errorFn: apiError,
  });
}

Upvotes: 0

Dadsquatch
Dadsquatch

Reputation: 566

You should be passing your res into res.json() and returning the results into your state.

componentDidMount() {
    console.log("component did mount");
    fetch("/user/list")
    .then(res => res.json())
    .then(users => 
      this.setState(users, 
        () => {
            console.log("list of users => " + users)
        })
    );
}

Upvotes: 0

Michael Jasper
Michael Jasper

Reputation: 8058

You are calling res.json() rather than returning res.json() from the first then on your fetch call

I've found this pattern to be helpful:

fetch(url)
   .then(res => res.ok ? res.json() : Promise.reject())

As your code is now, users (the parameter in the second then would be undefined, because you are not returning anything from the first then

Upvotes: 1

Taki
Taki

Reputation: 17654

you have to return the res.json() to use it in the next .then()

.then(res => {
    res.json();
})

should be

.then(res => 
    res.json();
)

Or

.then(res => {
    return res.json();
})

https://javascript.info/promise-chaining

Upvotes: 1

Related Questions