Использование then () для обещания, возвращаемого fetch, возвращает неопределенное значение в React - PullRequest
0 голосов
/ 21 июня 2019

Я следую этому уроку: https://github.com/callicoder/spring-security-react-ant-design-polls-app

У меня уже есть рабочий бэкэнд, который генерирует JWT, а также API возвращает данные текущего пользователя в http://localhost:8080/api/user/me с GET метод.Все хорошо на спине (протестировано с почтальоном).

Но у меня возникает проблема, когда я пытаюсь загрузить текущего пользователя из API в состояние моего App компонента.Идея состоит в том, чтобы создать маршрут к компоненту Login и передать ему ссылку на метод handleLogin, который выполняет getCurrentUser() и перенаправляет на главную страницу.

Все это выполняется с помощью импортафайла с именем APIUtils, который имеет методы для взаимодействия с API.В частности, он имеет общий метод request(), который возвращает обещание с использованием fetch и получает параметры запроса.Проблема в том, что я не могу получить ответ на обещание, возвращенное методом APIUtils/request().Он говорит, что он не определен.

App.js

//imports
class App extends Component {
  state = {
    currentUser: null
  }

  loadCurrentUser = () => {
    // getCurrentUser is imported from APIUtils/index.js
    getCurrentUser()
      .then(response => {
        this.setState({
          currentUser: response
        });
      })
      .catch(error => {
        console.log(error)
      });
  }

  handleLogin = () => {
        this.loadCurrentUser();
    this.props.history.push("/");
  }

  componentDidMount() {
    this.loadCurrentUser();
  }

  render () {
    return (
      <Switch>
        <Route exact path='/' component={Landing} />
        <Route path="/login" 
          render={
            (props) => <Login onLogin={this.handleLogin} {...props} />
        }/>
        </Route>
      </Switch>
    );
  }
}

export default withRouter(App);

APIUtils / index.js

const request = (options) => {
    const headers = new Headers({
            'Content-Type': 'application/json',
    })

    if(localStorage.getItem(ACCESS_TOKEN)) {
        headers.append('Authorization', 'Bearer ' + localStorage.getItem(ACCESS_TOKEN))
    }

    const defaults = { headers: headers };
    options = Object.assign({}, defaults, options);

    return fetch(options.url, options)
    .then(response => {
        response.json().then(json => {
            if(!response.ok) {
                return Promise.reject(json);
            }
            return json;
        })}
    );
}

// expects loginRequest = { email: 'something', password: 'something' }
export const login = (loginRequest) => {
    return request({
            url: API_BASE_URL + "/auth/signin",
            method: 'POST',
            body: JSON.stringify(loginRequest)
    });
}

export const getCurrentUser = () => {
    if(!localStorage.getItem(ACCESS_TOKEN)) {
        return Promise.reject("No access token set.");
    }
    return request({
            url: API_BASE_URL + "/user/me",
            method: 'GET'
    });
}

Login.js

class Login extends Component {

    state = {
        email: '',
        password: ''
    }

    handleChange = (event) => {
        this.setState({
            [event.target.id]: event.target.value
        });
    }

    handleSubmit = (event) => {
        event.preventDefault();
        const loginRequest = Object.assign({}, this.state);

        login(loginRequest)
            .then(response => {
                localStorage.setItem(ACCESS_TOKEN, response.accessToken);
                this.props.onLogin();
            }).catch(error => {
                if(error.status === 401) {
                    console.log('Your Username or Password is incorrect. Please try again!');
                } else {
                    console.log('Sorry! Something went wrong. Please try again!');                                         
                }
            });
    }

  render () {
        return (
            <React.Fragment>
        /* 
        * form using onSubmit={this.handleSubmit}
        * inputs using value={this.state.email} and onChange={this.handleChange}
        * button of type="submit"
        */
            </React.Fragment>
        );
    } 
}
export default Login;

При этом после того, как я вхожу в систему и загружаю целевую страницу, через консоль я проверил, и у меня есть токен в локальном хранилище, также запрос ()Метод в APIUtils возвращает ответ с URL: http://localhost:8080/api/user/me, и возвращает обещание json, содержащееся в коде, которое выглядит примерно так:

{
  "id": 23,
  "name": "john",
  "email": "new@mail.com"
}

Но когда я пытаюсь получить доступ к ответуиз getCurrentUser () в App.js с использованием then (), его ответ не определен, поэтому я не могу установить его в состояние.

1 Ответ

1 голос
/ 21 июня 2019

Вы не возвращаете результат fetch():

return fetch(options.url, options)
    .then(response => { // you forgot that this is also a function
        return response.json().then(json => { // <--- missing return!!
            if(!response.ok) {
                return Promise.reject(json);
            }
            return json;
        })}
    );

Я могу понять, почему вы, возможно, пропустили это. Это довольно легко пропустить. Вот почему вы должны использовать главную особенность Обещаний - причину, по которой они были изобретены - цепочка обещаний:

let ok = null;
return fetch(options.url, options)
    .then(response => {
        ok = response.ok;
        return response.json();
    })
    .then(json => {
        if (!ok) {
            return Promise.reject(json);
        }
        return json;
    });

Таким способом легче обнаружить пропущенный возврат, поскольку вы можете легко проверить, что каждый блок then имеет return оценку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...