简体   繁体   中英

Method returning undefined even though fetch succeeds?

I have two components, Client and App, and a fetch function. App is the child component of Client. I want to update Client's state using the return value from the method App calls. However, Client's state response is undefined after the fetch. I'm not sure why this code does not work.

import React, { Component } from 'react';
import './App.css';  

function post(user, token, data){
  console.log('fetching...')
  fetch(`/project`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Basic '+ btoa(user+':'+token),
    },
    body: JSON.stringify(data)
  }).then(r => {
      if (!r.ok)
        throw Error(r.status);
      r.json().then(r => {return(r)});
  }).catch(error => {throw Error(error)})
}

class Client extends Component {
  constructor(props) {
    super(props);
    this.state = {
      user: '',
      token: '111',
      project: {'project':'demo'},
      response: {},
    };

    this.updateState = this.updateState.bind(this);
  };


  updateState(){
    const { user, token, project } = this.state;
    post(user, token, project).then(text => this.setState({ response: text 
  }));
  }

  render() {
    return (
        <App updateState={this.updateState}/>
    )
  }
}

class App extends Component {      
  render() {
    return (
      <div className="App">
          <button onClick={ () => {
             this.props.updateState()} }>Fetch Project</button>
      </div>
    );
  }
}

EDIT: I changed my post() to this and it works:)

async function post(user, token, data){
  console.log('fetching...')
  const response = await fetch(`/project`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Basic '+ btoa(user+':'+token),
    },
    body: JSON.stringify(data)
  }).catch(error => {throw Error(error)});

  if(!response.ok)
    throw Error(response.status);
  
  const obj = await response.json();
  return(obj);
}

If you are working with promises, you can do something like this.

import React, { Component } from "react";
    async function post() {
      // fetch //
      return await fetch("https://hipsum.co/api/?type=hipster-centric");
    }

    class Client extends Component {
      constructor(props) {
        super(props);
        this.state = {
          response: "12"
        };
        this.updateState = this.updateState.bind(this);
      }

      async updateState(res) {
        const text = await res().then(res => res.text());
        this.setState({ response: text });
      }

      render() {
        return (
          <>
            {this.state.response}
            <App updateState={this.updateState} />
          </>
        );
      }
    }

    class App extends Component {
      render() {
        return (
          <div>
            <button
              onClick={() => {
                this.props.updateState(post);
              }}
            >
              Fetch
            </button>
          </div>
        );
      }
    }

    export default Client;

sandbox

It will be nice to know all the code for the fetch function but I think the problem is mostly here:

this.props.updateState(post())

That call is synchronous and the fetching process isn't. You need a better approach with await or promises or a callback.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM